From 6877bb7630a0f59b79fc3b141e902d3f0bacd087 Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Sat, 3 Aug 2024 18:03:29 +0000 Subject: Deploy mate-desktop/libmatekbd to github.com/mate-desktop/libmatekbd.git:gh-pages --- .../0.html | 2067 +++++++ .../1.html | 1863 ++++++ .../2.html | 781 +++ .../3.html | 6031 ++++++++++++++++++++ .../4.html | 1991 +++++++ .../index.html | 217 + .../stats.html | 173 + .../style.css | 177 + 8 files changed, 13300 insertions(+) create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/0.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/1.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/2.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/3.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/4.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/index.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/stats.html create mode 100644 2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/style.css (limited to '2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1') diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/0.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/0.html new file mode 100644 index 0000000..531f6ad --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/0.html @@ -0,0 +1,2067 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+
  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
/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <config.h>
+
+#include <memory.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n-lib.h>
+
+#include <matekbd-indicator.h>
+#include <matekbd-indicator-marshal.h>
+
+#include <matekbd-desktop-config.h>
+#include <matekbd-indicator-config.h>
+
+typedef struct _gki_globals {
+	XklEngine *engine;
+	XklConfigRegistry *registry;
+
+	MatekbdDesktopConfig cfg;
+	MatekbdIndicatorConfig ind_cfg;
+	MatekbdKeyboardConfig kbd_cfg;
+
+	const gchar *tooltips_format;
+	gchar **full_group_names;
+	gchar **short_group_names;
+	GSList *widget_instances;
+	GSList *images;
+} gki_globals;
+
+struct _MatekbdIndicatorPrivate {
+	gboolean set_parent_tooltips;
+	gdouble angle;
+};
+
+/* one instance for ALL widgets */
+static gki_globals globals;
+
+#define ForAllIndicators() \
+	{ \
+		GSList* cur; \
+		for (cur = globals.widget_instances; cur != NULL; cur = cur->next) { \
+			MatekbdIndicator * gki = (MatekbdIndicator*)cur->data;
+#define NextIndicator() \
+		} \
+	}
+
+G_DEFINE_TYPE (MatekbdIndicator, matekbd_indicator, GTK_TYPE_NOTEBOOK)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
+
+static void
+matekbd_indicator_global_init (void);
+static void
+matekbd_indicator_global_term (void);
+static GtkWidget *
+matekbd_indicator_prepare_drawing (MatekbdIndicator * gki, int group);
+static void
+matekbd_indicator_set_current_page_for_group (MatekbdIndicator * gki, int group);
+static void
+matekbd_indicator_set_current_page (MatekbdIndicator * gki);
+static void
+matekbd_indicator_cleanup (MatekbdIndicator * gki);
+static void
+matekbd_indicator_fill (MatekbdIndicator * gki);
+static void
+matekbd_indicator_set_tooltips (MatekbdIndicator * gki, const char *str);
+
+void
+matekbd_indicator_load_images ()
+{
+	int i;
+	GSList *image_filename;
+
+	globals.images = NULL;
+	matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+						    &globals.kbd_cfg);
+
+	if (!globals.ind_cfg.show_flags)
+		return;
+
+	image_filename = globals.ind_cfg.image_filenames;
+
+	for (i = xkl_engine_get_max_num_groups (globals.engine);
+	     --i >= 0; image_filename = image_filename->next) {
+		GdkPixbuf *image = NULL;
+		char *image_file = (char *) image_filename->data;
+
+		if (image_file != NULL) {
+			GError *gerror = NULL;
+			image =
+			    gdk_pixbuf_new_from_file (image_file, &gerror);
+			if (image == NULL) {
+				GtkWidget *dialog =
+				    gtk_message_dialog_new (NULL,
+							    GTK_DIALOG_DESTROY_WITH_PARENT,
+							    GTK_MESSAGE_ERROR,
+							    GTK_BUTTONS_OK,
+							    _
+							    ("There was an error loading an image: %s"),
+							    gerror->
+							    message);
+				g_signal_connect (G_OBJECT (dialog),
+						  "response",
+						  G_CALLBACK
+						  (gtk_widget_destroy),
+						  NULL);
+
+				gtk_window_set_resizable (GTK_WINDOW
+							  (dialog), FALSE);
+
+				gtk_widget_show (dialog);
+				g_error_free (gerror);
+			}
+			xkl_debug (150,
+				   "Image %d[%s] loaded -> %p[%dx%d]\n",
+				   i, image_file, image,
+				   gdk_pixbuf_get_width (image),
+				   gdk_pixbuf_get_height (image));
+		}
+		/* We append the image anyway - even if it is NULL! */
+		globals.images = g_slist_append (globals.images, image);
+	}
+}
+
+static void
+matekbd_indicator_free_images ()
+{
+	GdkPixbuf *pi;
+	GSList *img_node;
+
+	matekbd_indicator_config_free_image_filenames (&globals.ind_cfg);
+
+	while ((img_node = globals.images) != NULL) {
+		pi = GDK_PIXBUF (img_node->data);
+		/* It can be NULL - some images may be missing */
+		if (pi != NULL) {
+			g_object_unref (pi);
+		}
+		globals.images =
+		    g_slist_remove_link (globals.images, img_node);
+		g_slist_free_1 (img_node);
+	}
+}
+
+static void
+matekbd_indicator_update_images (void)
+{
+	matekbd_indicator_free_images ();
+	matekbd_indicator_load_images ();
+}
+
+void
+matekbd_indicator_set_tooltips (MatekbdIndicator * gki, const char *str)
+{
+	g_assert (str == NULL || g_utf8_validate (str, -1, NULL));
+
+	gtk_widget_set_tooltip_text (GTK_WIDGET (gki), str);
+
+	if (gki->priv->set_parent_tooltips) {
+		GtkWidget *parent =
+		    gtk_widget_get_parent (GTK_WIDGET (gki));
+		if (parent) {
+			gtk_widget_set_tooltip_text (parent, str);
+		}
+	}
+}
+
+void
+matekbd_indicator_cleanup (MatekbdIndicator * gki)
+{
+	int i;
+	GtkNotebook *notebook = GTK_NOTEBOOK (gki);
+
+	/* Do not remove the first page! It is the default page */
+	for (i = gtk_notebook_get_n_pages (notebook); --i > 0;) {
+		gtk_notebook_remove_page (notebook, i);
+	}
+}
+
+void
+matekbd_indicator_fill (MatekbdIndicator * gki)
+{
+	int grp;
+	int total_groups = xkl_engine_get_num_groups (globals.engine);
+	GtkNotebook *notebook = GTK_NOTEBOOK (gki);
+
+	for (grp = 0; grp < total_groups; grp++) {
+		GtkWidget *page;
+		page = matekbd_indicator_prepare_drawing (gki, grp);
+
+		if (page == NULL)
+			page = gtk_label_new ("");
+
+		gtk_notebook_append_page (notebook, page, NULL);
+		gtk_widget_show_all (page);
+	}
+}
+
+static gboolean matekbd_indicator_key_pressed(GtkWidget* widget, GdkEventKey* event, MatekbdIndicator* gki)
+{
+	switch (event->keyval)
+	{
+			case GDK_KEY_KP_Enter:
+			case GDK_KEY_ISO_Enter:
+			case GDK_KEY_3270_Enter:
+			case GDK_KEY_Return:
+			case GDK_KEY_space:
+			case GDK_KEY_KP_Space:
+			matekbd_desktop_config_lock_next_group(&globals.cfg);
+			return TRUE;
+		default:
+			break;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+matekbd_indicator_button_pressed (GtkWidget *
+			       widget,
+			       GdkEventButton * event, MatekbdIndicator * gki)
+{
+	GtkWidget *img = gtk_bin_get_child (GTK_BIN (widget));
+	GtkAllocation allocation;
+	gtk_widget_get_allocation (img, &allocation);
+	xkl_debug (150, "Flag img size %d x %d\n",
+		   allocation.width, allocation.height);
+	if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+		xkl_debug (150, "Mouse button pressed on applet\n");
+		matekbd_desktop_config_lock_next_group (&globals.cfg);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+draw_flag (GtkWidget * flag, cairo_t * cr, GdkPixbuf * image)
+{
+	/* Image width and height */
+	int iw = gdk_pixbuf_get_width (image);
+	int ih = gdk_pixbuf_get_height (image);
+	GtkAllocation allocation;
+	double xwiratio, ywiratio, wiratio;
+
+	gtk_widget_get_allocation (flag, &allocation);
+
+	/* widget-to-image scales, X and Y */
+	xwiratio = 1.0 * allocation.width / iw;
+	ywiratio = 1.0 * allocation.height / ih;
+	wiratio = xwiratio < ywiratio ? xwiratio : ywiratio;
+
+	/* transform cairo context */
+	cairo_translate (cr, allocation.width / 2.0, allocation.height / 2.0);
+	cairo_scale (cr, wiratio, wiratio);
+	cairo_translate (cr, - iw / 2.0, - ih / 2.0);
+
+	gdk_cairo_set_source_pixbuf (cr, image, 0, 0);
+	cairo_paint (cr);
+}
+
+gchar *
+matekbd_indicator_extract_layout_name (int group, XklEngine * engine,
+				    MatekbdKeyboardConfig * kbd_cfg,
+				    gchar ** short_group_names,
+				    gchar ** full_group_names)
+{
+	char *layout_name = NULL;
+	if (group < g_strv_length (short_group_names)) {
+		if (xkl_engine_get_features (engine) &
+		    XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+			char *full_layout_name =
+			    kbd_cfg->layouts_variants[group];
+			char *variant_name;
+			if (!matekbd_keyboard_config_split_items
+			    (full_layout_name, &layout_name,
+			     &variant_name))
+				/* just in case */
+				layout_name = full_layout_name;
+
+			/* make it freeable */
+			layout_name = g_strdup (layout_name);
+
+			if (short_group_names != NULL) {
+				char *short_group_name =
+				    short_group_names[group];
+				if (short_group_name != NULL
+				    && *short_group_name != '\0') {
+					/* drop the long name */
+					g_free (layout_name);
+					layout_name =
+					    g_strdup (short_group_name);
+				}
+			}
+		} else {
+			layout_name = g_strdup (full_group_names[group]);
+		}
+	}
+
+	if (layout_name == NULL)
+		layout_name = g_strdup ("");
+
+	return layout_name;
+}
+
+gchar *
+matekbd_indicator_create_label_title (int group, GHashTable ** ln2cnt_map,
+				   gchar * layout_name)
+{
+	gpointer pcounter = NULL;
+	char *prev_layout_name = NULL;
+	char *lbl_title = NULL;
+	int counter = 0;
+
+	if (group == 0) {
+		*ln2cnt_map =
+		    g_hash_table_new_full (g_str_hash, g_str_equal,
+					   g_free, NULL);
+	}
+
+	/* Process layouts with repeating description */
+	if (g_hash_table_lookup_extended
+	    (*ln2cnt_map, layout_name, (gpointer *) & prev_layout_name,
+	     &pcounter)) {
+		/* "next" same description */
+		gchar appendix[10] = "";
+		gint utf8length;
+		gunichar cidx;
+		counter = GPOINTER_TO_INT (pcounter);
+		/* Unicode subscript 2, 3, 4 */
+		cidx = 0x2081 + counter;
+		utf8length = g_unichar_to_utf8 (cidx, appendix);
+		appendix[utf8length] = '\0';
+		lbl_title = g_strconcat (layout_name, appendix, NULL);
+	} else {
+		/* "first" time this description */
+		lbl_title = g_strdup (layout_name);
+	}
+	g_hash_table_insert (*ln2cnt_map, layout_name,
+			     GINT_TO_POINTER (counter + 1));
+	return lbl_title;
+}
+
+static GtkWidget *
+matekbd_indicator_prepare_drawing (MatekbdIndicator * gki, int group)
+{
+	gpointer pimage;
+	GdkPixbuf *image;
+	GtkWidget *ebox;
+
+	pimage = g_slist_nth_data (globals.images, group);
+	ebox = gtk_event_box_new ();
+	gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE);
+	if (globals.ind_cfg.show_flags) {
+		GtkWidget *flag;
+		if (pimage == NULL)
+			return NULL;
+		image = GDK_PIXBUF (pimage);
+		flag = gtk_drawing_area_new ();
+		gtk_widget_add_events (GTK_WIDGET (flag),
+				       GDK_BUTTON_PRESS_MASK);
+		g_signal_connect (G_OBJECT (flag), "draw",
+		                  G_CALLBACK (draw_flag), image);
+		gtk_container_add (GTK_CONTAINER (ebox), flag);
+	} else {
+		char *lbl_title = NULL;
+		char *layout_name = NULL;
+		GtkWidget *label;
+		static GHashTable *ln2cnt_map = NULL;
+
+		layout_name =
+		    matekbd_indicator_extract_layout_name (group,
+							globals.engine,
+							&globals.kbd_cfg,
+							globals.short_group_names,
+							globals.full_group_names);
+
+		lbl_title =
+		    matekbd_indicator_create_label_title (group,
+						       &ln2cnt_map,
+						       layout_name);
+
+		label = gtk_label_new (lbl_title);
+		gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
+		gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+		gtk_widget_set_margin_start (label, 2);
+		gtk_widget_set_margin_end (label, 2);
+		gtk_widget_set_margin_top (label, 2);
+		gtk_widget_set_margin_bottom (label, 2);
+		g_free (lbl_title);
+		gtk_label_set_angle (GTK_LABEL (label), gki->priv->angle);
+
+		if (group + 1 ==
+		    xkl_engine_get_num_groups (globals.engine)) {
+			g_hash_table_destroy (ln2cnt_map);
+			ln2cnt_map = NULL;
+		}
+
+		gtk_container_add (GTK_CONTAINER (ebox), label);
+	}
+
+	g_signal_connect (G_OBJECT (ebox),
+			  "button_press_event",
+			  G_CALLBACK (matekbd_indicator_button_pressed), gki);
+
+	g_signal_connect (G_OBJECT (gki),
+			  "key_press_event",
+			  G_CALLBACK (matekbd_indicator_key_pressed), gki);
+
+	/* We have everything prepared for that size */
+
+	return ebox;
+}
+
+static void
+matekbd_indicator_update_tooltips (MatekbdIndicator * gki)
+{
+	XklState *state = xkl_engine_get_current_state (globals.engine);
+	gchar *buf;
+	if (state == NULL || state->group < 0
+	    || state->group >= g_strv_length (globals.full_group_names))
+		return;
+
+	buf = g_strdup_printf (globals.tooltips_format,
+			       globals.full_group_names[state->group]);
+
+	matekbd_indicator_set_tooltips (gki, buf);
+	g_free (buf);
+}
+
+static void
+matekbd_indicator_parent_set (GtkWidget * gki, GtkWidget * previous_parent)
+{
+	matekbd_indicator_update_tooltips (MATEKBD_INDICATOR (gki));
+}
+
+void
+matekbd_indicator_reinit_ui (MatekbdIndicator * gki)
+{
+	matekbd_indicator_cleanup (gki);
+	matekbd_indicator_fill (gki);
+
+	matekbd_indicator_set_current_page (gki);
+
+	g_signal_emit_by_name (gki, "reinit-ui");
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_cfg_changed (GSettings *settings,
+			       gchar     *key,
+			       gpointer   user_data)
+{
+	xkl_debug (100,
+		   "General configuration changed in GSettings - reiniting...\n");
+	matekbd_desktop_config_load_from_gsettings (&globals.cfg);
+	matekbd_desktop_config_activate (&globals.cfg);
+	ForAllIndicators () {
+		matekbd_indicator_reinit_ui (gki);
+	} NextIndicator ();
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_ind_cfg_changed (GSettings *settings,
+				   gchar     *key,
+				   gpointer   user_data)
+{
+	xkl_debug (100,
+		   "Applet configuration changed in GSettings - reiniting...\n");
+	matekbd_indicator_config_load_from_gsettings (&globals.ind_cfg);
+	matekbd_indicator_update_images ();
+	matekbd_indicator_config_activate (&globals.ind_cfg);
+
+	ForAllIndicators () {
+		matekbd_indicator_reinit_ui (gki);
+	} NextIndicator ();
+}
+
+static void
+matekbd_indicator_load_group_names (const gchar ** layout_ids,
+				 const gchar ** variant_ids)
+{
+	if (!matekbd_desktop_config_load_group_descriptions
+	    (&globals.cfg, globals.registry, layout_ids, variant_ids,
+	     &globals.short_group_names, &globals.full_group_names)) {
+		/* We just populate no short names (remain NULL) -
+		 * full names are going to be used anyway */
+		gint i, total_groups =
+		    xkl_engine_get_num_groups (globals.engine);
+		globals.full_group_names =
+		    g_new0 (gchar *, total_groups + 1);
+
+		if (xkl_engine_get_features (globals.engine) &
+		    XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+			gchar **lst = globals.kbd_cfg.layouts_variants;
+			for (i = 0; *lst; lst++, i++) {
+				globals.full_group_names[i] =
+				    g_strdup ((char *) *lst);
+			}
+		} else {
+			for (i = total_groups; --i >= 0;) {
+				globals.full_group_names[i] =
+				    g_strdup_printf ("Group %d", i);
+			}
+		}
+	}
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_kbd_cfg_callback (MatekbdIndicator * gki)
+{
+	XklConfigRec *xklrec = xkl_config_rec_new ();
+	xkl_debug (100,
+		   "XKB configuration changed on X Server - reiniting...\n");
+
+	matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+						  xklrec);
+	matekbd_indicator_update_images ();
+
+	g_strfreev (globals.full_group_names);
+	globals.full_group_names = NULL;
+
+	if (globals.short_group_names != NULL) {
+		g_strfreev (globals.short_group_names);
+		globals.short_group_names = NULL;
+	}
+
+	matekbd_indicator_load_group_names ((const gchar **) xklrec->layouts,
+					 (const gchar **)
+					 xklrec->variants);
+
+	ForAllIndicators () {
+		matekbd_indicator_reinit_ui (gki);
+	} NextIndicator ();
+	g_object_unref (G_OBJECT (xklrec));
+}
+
+/* Should be called once for all applets */
+static void
+matekbd_indicator_state_callback (XklEngine * engine,
+			       XklEngineStateChange changeType,
+			       gint group, gboolean restore)
+{
+	xkl_debug (150, "group is now %d, restore: %d\n", group, restore);
+
+	if (changeType == GROUP_CHANGED) {
+		ForAllIndicators () {
+			xkl_debug (200, "do repaint\n");
+			matekbd_indicator_set_current_page_for_group
+			    (gki, group);
+		}
+		NextIndicator ();
+	}
+}
+
+void
+matekbd_indicator_set_current_page (MatekbdIndicator * gki)
+{
+	XklState *cur_state;
+	cur_state = xkl_engine_get_current_state (globals.engine);
+	if (cur_state->group >= 0)
+		matekbd_indicator_set_current_page_for_group (gki,
+							   cur_state->
+							   group);
+}
+
+void
+matekbd_indicator_set_current_page_for_group (MatekbdIndicator * gki, int group)
+{
+	xkl_debug (200, "Revalidating for group %d\n", group);
+
+	gtk_notebook_set_current_page (GTK_NOTEBOOK (gki), group + 1);
+
+	matekbd_indicator_update_tooltips (gki);
+}
+
+/* Should be called once for all widgets */
+static GdkFilterReturn
+matekbd_indicator_filter_x_evt (GdkXEvent * xev, GdkEvent * event)
+{
+	XEvent *xevent = (XEvent *) xev;
+
+	xkl_engine_filter_events (globals.engine, xevent);
+	switch (xevent->type) {
+	case ReparentNotify:
+		{
+			XReparentEvent *rne = (XReparentEvent *) xev;
+
+			ForAllIndicators () {
+				GdkWindow *w =
+				    gtk_widget_get_parent_window
+				    (GTK_WIDGET (gki));
+
+				/* compare the indicator's parent window with the even window */
+				if (w != NULL
+				    && GDK_WINDOW_XID (w) == rne->window) {
+					/* if so - make it transparent... */
+					xkl_engine_set_window_transparent
+					    (globals.engine, rne->window,
+					     TRUE);
+				}
+			}
+			NextIndicator ()
+		}
+		break;
+	}
+	return GDK_FILTER_CONTINUE;
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_start_listen (void)
+{
+	gdk_window_add_filter (NULL, (GdkFilterFunc)
+			       matekbd_indicator_filter_x_evt, NULL);
+	gdk_window_add_filter (gdk_get_default_root_window (),
+			       (GdkFilterFunc)
+			       matekbd_indicator_filter_x_evt, NULL);
+
+	xkl_engine_start_listen (globals.engine,
+				 XKLL_TRACK_KEYBOARD_STATE);
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_stop_listen (void)
+{
+	xkl_engine_stop_listen (globals.engine, XKLL_TRACK_KEYBOARD_STATE);
+
+	gdk_window_remove_filter (NULL, (GdkFilterFunc)
+				  matekbd_indicator_filter_x_evt, NULL);
+	gdk_window_remove_filter
+	    (gdk_get_default_root_window (),
+	     (GdkFilterFunc) matekbd_indicator_filter_x_evt, NULL);
+}
+
+static gboolean
+matekbd_indicator_scroll (GtkWidget * gki, GdkEventScroll * event)
+{
+	/* mouse wheel events should be ignored, otherwise funny effects appear */
+	return TRUE;
+}
+
+static void matekbd_indicator_init(MatekbdIndicator* gki)
+{
+	GtkWidget *def_drawing;
+	GtkNotebook *notebook;
+
+	if (!g_slist_length(globals.widget_instances))
+	{
+		matekbd_indicator_global_init();
+	}
+
+	gki->priv = g_new0 (MatekbdIndicatorPrivate, 1);
+
+	notebook = GTK_NOTEBOOK (gki);
+
+	xkl_debug (100, "Initiating the widget startup process for %p\n", gki);
+
+	gtk_notebook_set_show_tabs (notebook, FALSE);
+	gtk_notebook_set_show_border (notebook, FALSE);
+
+	def_drawing =
+	    gtk_image_new_from_icon_name ("process-stop",
+				      GTK_ICON_SIZE_BUTTON);
+
+	gtk_notebook_append_page (notebook, def_drawing,
+				  gtk_label_new (""));
+
+	if (globals.engine == NULL) {
+		matekbd_indicator_set_tooltips (gki,
+					     _
+					     ("XKB initialization error"));
+		return;
+	}
+
+	matekbd_indicator_set_tooltips (gki, NULL);
+
+	matekbd_indicator_fill (gki);
+	matekbd_indicator_set_current_page (gki);
+
+	gtk_widget_add_events (GTK_WIDGET (gki), GDK_BUTTON_PRESS_MASK);
+
+	/* append AFTER all initialization work is finished */
+	globals.widget_instances =
+	    g_slist_append (globals.widget_instances, gki);
+}
+
+static void
+matekbd_indicator_finalize (GObject * obj)
+{
+	MatekbdIndicator *gki = MATEKBD_INDICATOR (obj);
+	xkl_debug (100,
+		   "Starting the mate-kbd-indicator widget shutdown process for %p\n",
+		   gki);
+
+	/* remove BEFORE all termination work is finished */
+	globals.widget_instances =
+	    g_slist_remove (globals.widget_instances, gki);
+
+	matekbd_indicator_cleanup (gki);
+
+	xkl_debug (100,
+		   "The instance of mate-kbd-indicator successfully finalized\n");
+
+	g_free (gki->priv);
+
+	G_OBJECT_CLASS (matekbd_indicator_parent_class)->finalize (obj);
+
+	if (!g_slist_length (globals.widget_instances))
+		matekbd_indicator_global_term ();
+}
+
+static void
+matekbd_indicator_global_term (void)
+{
+	xkl_debug (100, "*** Last  MatekbdIndicator instance *** \n");
+	matekbd_indicator_stop_listen ();
+
+	matekbd_desktop_config_stop_listen (&globals.cfg);
+	matekbd_indicator_config_stop_listen (&globals.ind_cfg);
+
+	matekbd_indicator_config_term (&globals.ind_cfg);
+	matekbd_keyboard_config_term (&globals.kbd_cfg);
+	matekbd_desktop_config_term (&globals.cfg);
+
+	g_object_unref (G_OBJECT (globals.registry));
+	globals.registry = NULL;
+	g_object_unref (G_OBJECT (globals.engine));
+	globals.engine = NULL;
+	xkl_debug (100, "*** Terminated globals *** \n");
+}
+
+static void
+matekbd_indicator_class_init (MatekbdIndicatorClass * klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+	xkl_debug (100, "*** First MatekbdIndicator instance *** \n");
+
+	memset (&globals, 0, sizeof (globals));
+
+	/* Initing some global vars */
+	globals.tooltips_format = "%s";
+
+	/* Initing vtable */
+	object_class->finalize = matekbd_indicator_finalize;
+
+	widget_class->scroll_event = matekbd_indicator_scroll;
+	widget_class->parent_set = matekbd_indicator_parent_set;
+
+	/* Signals */
+	g_signal_new ("reinit-ui", MATEKBD_TYPE_INDICATOR,
+		      G_SIGNAL_RUN_LAST,
+		      G_STRUCT_OFFSET (MatekbdIndicatorClass, reinit_ui),
+		      NULL, NULL, matekbd_indicator_VOID__VOID,
+		      G_TYPE_NONE, 0);
+}
+
+static void
+matekbd_indicator_global_init (void)
+{
+	XklConfigRec *xklrec = xkl_config_rec_new ();
+
+	globals.engine = xkl_engine_get_instance(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()));
+
+	if (globals.engine == NULL)
+	{
+		xkl_debug (0, "Libxklavier initialization error");
+		return;
+	}
+
+	g_signal_connect (globals.engine, "X-state-changed",
+			  G_CALLBACK (matekbd_indicator_state_callback),
+			  NULL);
+	g_signal_connect (globals.engine, "X-config-changed",
+			  G_CALLBACK (matekbd_indicator_kbd_cfg_callback),
+			  NULL);
+
+	matekbd_desktop_config_init (&globals.cfg, globals.engine);
+	matekbd_keyboard_config_init (&globals.kbd_cfg, globals.engine);
+	matekbd_indicator_config_init (&globals.ind_cfg, globals.engine);
+
+	matekbd_desktop_config_start_listen (&globals.cfg,
+					  (GCallback)
+					  matekbd_indicator_cfg_changed,
+					  NULL);
+	matekbd_indicator_config_start_listen (&globals.ind_cfg,
+					    (GCallback)
+					    matekbd_indicator_ind_cfg_changed,
+					    NULL);
+
+	matekbd_desktop_config_load_from_gsettings (&globals.cfg);
+	matekbd_desktop_config_activate (&globals.cfg);
+
+	globals.registry =
+	    xkl_config_registry_get_instance (globals.engine);
+	xkl_config_registry_load (globals.registry,
+				  globals.cfg.load_extra_items);
+
+	matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+						  xklrec);
+
+	matekbd_indicator_config_load_from_gsettings (&globals.ind_cfg);
+	matekbd_indicator_update_images ();
+	matekbd_indicator_config_activate (&globals.ind_cfg);
+
+	matekbd_indicator_load_group_names ((const gchar **) xklrec->layouts,
+					 (const gchar **)
+					 xklrec->variants);
+	g_object_unref (G_OBJECT (xklrec));
+
+	matekbd_indicator_start_listen ();
+
+	xkl_debug (100, "*** Inited globals *** \n");
+}
+
+GtkWidget *
+matekbd_indicator_new (void)
+{
+	return
+	    GTK_WIDGET (g_object_new (matekbd_indicator_get_type (), NULL));
+}
+
+void
+matekbd_indicator_set_parent_tooltips (MatekbdIndicator * gki, gboolean spt)
+{
+	gki->priv->set_parent_tooltips = spt;
+	matekbd_indicator_update_tooltips (gki);
+}
+
+void
+matekbd_indicator_set_tooltips_format (const gchar format[])
+{
+	globals.tooltips_format = format;
+	ForAllIndicators ()
+	    matekbd_indicator_update_tooltips (gki);
+	NextIndicator ()
+}
+
+/**
+ * matekbd_indicator_get_xkl_engine:
+ *
+ * Returns: (transfer none): The engine shared by all MatekbdIndicator objects
+ */
+XklEngine *
+matekbd_indicator_get_xkl_engine ()
+{
+	return globals.engine;
+}
+
+/**
+ * matekbd_indicator_get_group_names:
+ *
+ * Returns: (transfer none) (array zero-terminated=1): List of group names
+ */
+gchar **
+matekbd_indicator_get_group_names ()
+{
+	return globals.full_group_names;
+}
+
+gchar *
+matekbd_indicator_get_image_filename (guint group)
+{
+	if (!globals.ind_cfg.show_flags)
+		return NULL;
+	return matekbd_indicator_config_get_images_file (&globals.ind_cfg,
+						      &globals.kbd_cfg,
+						      group);
+}
+
+gdouble
+matekbd_indicator_get_max_width_height_ratio (void)
+{
+	gdouble rv = 0.0;
+	GSList *ip = globals.images;
+	if (!globals.ind_cfg.show_flags)
+		return 0;
+	while (ip != NULL) {
+		GdkPixbuf *img = GDK_PIXBUF (ip->data);
+		gdouble r =
+		    1.0 * gdk_pixbuf_get_width (img) /
+		    gdk_pixbuf_get_height (img);
+		if (r > rv)
+			rv = r;
+		ip = ip->next;
+	}
+	return rv;
+}
+
+void
+matekbd_indicator_set_angle (MatekbdIndicator * gki, gdouble angle)
+{
+	gki->priv->angle = angle;
+}
+
+ +
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/1.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/1.html new file mode 100644 index 0000000..832100e --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/1.html @@ -0,0 +1,1863 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+
  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
/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <matekbd-keyboard-config.h>
+#include <matekbd-config-private.h>
+#include <matekbd-util.h>
+
+/*
+ * MatekbdKeyboardConfig
+ */
+#define MATEKBD_KEYBOARD_CONFIG_SCHEMA MATEKBD_CONFIG_SCHEMA ".kbd"
+
+#define GROUP_SWITCHERS_GROUP "grp"
+#define DEFAULT_GROUP_SWITCH "grp:shift_caps_toggle"
+
+const gchar MATEKBD_KEYBOARD_CONFIG_KEY_MODEL[] = "model";
+const gchar MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[] = "layouts";
+const gchar MATEKBD_KEYBOARD_CONFIG_KEY_OPTIONS[] = "options";
+
+const gchar *MATEKBD_KEYBOARD_CONFIG_ACTIVE[] = {
+	MATEKBD_KEYBOARD_CONFIG_KEY_MODEL,
+	MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
+	MATEKBD_KEYBOARD_CONFIG_KEY_OPTIONS
+};
+
+/*
+ * static common functions
+ */
+
+static gboolean
+matekbd_strv_equal (gchar ** l1, gchar ** l2)
+{
+	if (l1 == l2)
+		return TRUE;
+	if (l1 == NULL)
+		return g_strv_length (l2) == 0;
+	if (l2 == NULL)
+		return g_strv_length (l1) == 0;
+
+	while ((*l1 != NULL) && (*l2 != NULL)) {
+		if (*l1 != *l2) {
+			if (*l1 && *l2) {
+				if (g_ascii_strcasecmp (*l1, *l2))
+					return FALSE;
+			} else
+				return FALSE;
+		}
+
+		l1++;
+		l2++;
+	}
+	return (*l1 == NULL) && (*l2 == NULL);
+}
+
+gboolean
+matekbd_keyboard_config_get_lv_descriptions (XklConfigRegistry *
+					  config_registry,
+					  const gchar * layout_name,
+					  const gchar * variant_name,
+					  gchar ** layout_short_descr,
+					  gchar ** layout_descr,
+					  gchar ** variant_short_descr,
+					  gchar ** variant_descr)
+{
+	/* TODO make it not static */
+	static XklConfigItem *litem = NULL;
+	static XklConfigItem *vitem = NULL;
+
+	if (litem == NULL)
+		litem = xkl_config_item_new ();
+	if (vitem == NULL)
+		vitem = xkl_config_item_new ();
+
+	layout_name = g_strdup (layout_name);
+
+	g_snprintf (litem->name, sizeof litem->name, "%s", layout_name);
+	if (xkl_config_registry_find_layout (config_registry, litem)) {
+		*layout_short_descr = litem->short_description;
+		*layout_descr = litem->description;
+	} else
+		*layout_short_descr = *layout_descr = NULL;
+
+	if (variant_name != NULL) {
+		variant_name = g_strdup (variant_name);
+		g_snprintf (vitem->name, sizeof vitem->name, "%s",
+			    variant_name);
+		if (xkl_config_registry_find_variant
+		    (config_registry, layout_name, vitem)) {
+			*variant_short_descr = vitem->short_description;
+			*variant_descr = vitem->description;
+		} else
+			*variant_short_descr = *variant_descr = NULL;
+
+		g_free ((char *) variant_name);
+	} else
+		*variant_descr = NULL;
+
+	g_free ((char *) layout_name);
+	return *layout_descr != NULL;
+}
+
+/*
+ * extern common functions
+ */
+const gchar *
+matekbd_keyboard_config_merge_items (const gchar * parent,
+				  const gchar * child)
+{
+	static gchar buffer[XKL_MAX_CI_NAME_LENGTH * 2 - 1];
+	*buffer = '\0';
+	if (parent != NULL) {
+		if (strlen (parent) >= XKL_MAX_CI_NAME_LENGTH)
+			return NULL;
+		strcat (buffer, parent);
+	}
+	if (child != NULL && *child != 0) {
+		if (strlen (child) >= XKL_MAX_CI_NAME_LENGTH)
+			return NULL;
+		strcat (buffer, "\t");
+		strcat (buffer, child);
+	}
+	return buffer;
+}
+
+gboolean
+matekbd_keyboard_config_split_items (const gchar * merged, gchar ** parent,
+				  gchar ** child)
+{
+	static gchar pbuffer[XKL_MAX_CI_NAME_LENGTH];
+	static gchar cbuffer[XKL_MAX_CI_NAME_LENGTH];
+	int plen;
+	const gchar *pos;
+	*parent = *child = NULL;
+
+	if (merged == NULL)
+		return FALSE;
+
+	pos = strchr (merged, '\t');
+	if (pos == NULL) {
+		plen = strlen (merged);
+	} else {
+		plen = pos - merged;
+		if (strlen (pos + 1) >= XKL_MAX_CI_NAME_LENGTH)
+			return FALSE;
+		strcpy (*child = cbuffer, pos + 1);
+	}
+	if (plen >= XKL_MAX_CI_NAME_LENGTH)
+		return FALSE;
+	memcpy (*parent = pbuffer, merged, plen);
+	pbuffer[plen] = '\0';
+	return TRUE;
+}
+
+/*
+ * static MatekbdKeyboardConfig functions
+ */
+static void
+matekbd_keyboard_config_copy_from_xkl_config (MatekbdKeyboardConfig * kbd_config,
+					   XklConfigRec * pdata)
+{
+	char **p, **p1;
+	int i;
+	matekbd_keyboard_config_model_set (kbd_config, pdata->model);
+	xkl_debug (150, "Loaded Kbd model: [%s]\n", pdata->model);
+
+	/* Layouts */
+	g_strfreev (kbd_config->layouts_variants);
+	kbd_config->layouts_variants = NULL;
+	if (pdata->layouts != NULL) {
+		p = pdata->layouts;
+		p1 = pdata->variants;
+		kbd_config->layouts_variants =
+		    g_new0 (gchar *, g_strv_length (pdata->layouts) + 1);
+		i = 0;
+		while (*p != NULL) {
+			const gchar *full_layout =
+			    matekbd_keyboard_config_merge_items (*p, *p1);
+			xkl_debug (150,
+				   "Loaded Kbd layout (with variant): [%s]\n",
+				   full_layout);
+			kbd_config->layouts_variants[i++] =
+			    g_strdup (full_layout);
+			p++;
+			p1++;
+		}
+	}
+
+	/* Options */
+	g_strfreev (kbd_config->options);
+	kbd_config->options = NULL;
+
+	if (pdata->options != NULL) {
+		p = pdata->options;
+		kbd_config->options =
+		    g_new0 (gchar *, g_strv_length (pdata->options) + 1);
+		i = 0;
+		while (*p != NULL) {
+			char group[XKL_MAX_CI_NAME_LENGTH];
+			char *option = *p;
+			char *delim =
+			    (option != NULL) ? strchr (option, ':') : NULL;<--- Condition 'option!=NULL' is always true
+			int len;
+			if ((delim != NULL) &&
+			    ((len =
+			      (delim - option)) <
+			     XKL_MAX_CI_NAME_LENGTH)) {
+				strncpy (group, option, len);
+				group[len] = 0;
+				xkl_debug (150,
+					   "Loaded Kbd option: [%s][%s]\n",
+					   group, option);
+				matekbd_keyboard_config_options_set
+				    (kbd_config, i++, group, option);
+			}
+			p++;
+		}
+	}
+}
+
+static void
+matekbd_keyboard_config_copy_to_xkl_config (MatekbdKeyboardConfig * kbd_config,
+					 XklConfigRec * pdata)
+{
+	int i;
+	int num_layouts, num_options;
+	pdata->model =
+	    (kbd_config->model ==
+	     NULL) ? NULL : g_strdup (kbd_config->model);
+
+	num_layouts =
+	    (kbd_config->layouts_variants ==
+	     NULL) ? 0 : g_strv_length (kbd_config->layouts_variants);
+	num_options =
+	    (kbd_config->options ==
+	     NULL) ? 0 : g_strv_length (kbd_config->options);
+
+	xkl_debug (150, "Taking %d layouts\n", num_layouts);
+	if (num_layouts != 0) {
+		gchar **the_layout_variant = kbd_config->layouts_variants;
+		char **p1 = pdata->layouts =
+		    g_new0 (char *, num_layouts + 1);
+		char **p2 = pdata->variants =
+		    g_new0 (char *, num_layouts + 1);
+		for (i = num_layouts; --i >= 0;) {
+			char *layout, *variant;
+			if (matekbd_keyboard_config_split_items
+			    (*the_layout_variant, &layout, &variant)
+			    && variant != NULL) {
+				*p1 =
+				    (layout ==
+				     NULL) ? g_strdup ("") :
+				    g_strdup (layout);
+				*p2 =
+				    (variant ==<--- Condition 'variant==NULL' is always false
+				     NULL) ? g_strdup ("") :
+				    g_strdup (variant);
+			} else {
+				*p1 =
+				    (*the_layout_variant ==
+				     NULL) ? g_strdup ("") :
+				    g_strdup (*the_layout_variant);
+				*p2 = g_strdup ("");
+			}
+			xkl_debug (150, "Adding [%s]/%p and [%s]/%p\n",
+				   *p1 ? *p1 : "(nil)", *p1,
+				   *p2 ? *p2 : "(nil)", *p2);
+			p1++;
+			p2++;
+			the_layout_variant++;
+		}
+	}
+
+	if (num_options != 0) {
+		gchar **the_option = kbd_config->options;
+		char **p = pdata->options =
+		    g_new0 (char *, num_options + 1);
+		for (i = num_options; --i >= 0;) {
+			char *group, *option;
+			if (matekbd_keyboard_config_split_items
+			    (*the_option, &group, &option)
+			    && option != NULL)
+				*(p++) = g_strdup (option);
+			else {
+				*(p++) = g_strdup ("");
+				xkl_debug (150, "Could not split [%s]\n",
+					   *the_option);
+			}
+			the_option++;
+		}
+	}
+}
+
+static void
+matekbd_keyboard_config_load_params (MatekbdKeyboardConfig * kbd_config,
+				  const gchar * param_names[])
+{
+	gchar *pc;
+
+	pc = g_settings_get_string (kbd_config->settings, param_names[0]);
+	if (pc == NULL) {
+		matekbd_keyboard_config_model_set (kbd_config, NULL);
+	} else {
+		matekbd_keyboard_config_model_set (kbd_config, pc);
+		g_free (pc);
+	}
+	xkl_debug (150, "Loaded Kbd model: [%s]\n",
+		   kbd_config->model ? kbd_config->model : "(null)");
+
+	g_strfreev (kbd_config->layouts_variants);
+
+	kbd_config->layouts_variants =
+	    g_settings_get_strv (kbd_config->settings, param_names[1]);
+
+	if (kbd_config->layouts_variants != NULL
+	    && kbd_config->layouts_variants[0] == NULL) {
+		g_strfreev (kbd_config->layouts_variants);
+		kbd_config->layouts_variants = NULL;
+	}
+
+	g_strfreev (kbd_config->options);
+
+	kbd_config->options =
+	    g_settings_get_strv (kbd_config->settings, param_names[2]);
+
+	if (kbd_config->options != NULL && kbd_config->options[0] == NULL) {
+		g_strfreev (kbd_config->options);
+		kbd_config->options = NULL;
+	}
+}
+
+static void
+matekbd_keyboard_config_save_params (MatekbdKeyboardConfig * kbd_config,
+				  const gchar * param_names[])
+{
+	gchar **pl;
+
+	if (kbd_config->model)
+		g_settings_set_string (kbd_config->settings, param_names[0],
+				       kbd_config->model);
+	else
+		g_settings_set_string (kbd_config->settings, param_names[0],
+				       NULL);
+	xkl_debug (150, "Saved Kbd model: [%s]\n",
+		   kbd_config->model ? kbd_config->model : "(null)");
+
+	if (kbd_config->layouts_variants) {
+		pl = kbd_config->layouts_variants;
+		while (*pl != NULL) {
+			xkl_debug (150, "Saved Kbd layout: [%s]\n", *pl);
+			pl++;
+		}
+		g_settings_set_strv (kbd_config->settings,
+				     param_names[1],
+				     (const gchar * const *)
+				     kbd_config->layouts_variants);
+	} else {
+		xkl_debug (150, "Saved Kbd layouts: []\n");
+		g_settings_set_strv (kbd_config->settings,
+				     param_names[1], NULL);
+	}
+
+	if (kbd_config->options) {
+		pl = kbd_config->options;
+		while (*pl != NULL) {
+			xkl_debug (150, "Saved Kbd option: [%s]\n", *pl);
+			pl++;
+		}
+		g_settings_set_strv (kbd_config->settings,
+				     param_names[2],
+				     (const gchar *
+				      const *) kbd_config->options);
+	} else {
+		xkl_debug (150, "Saved Kbd options: []\n");
+		g_settings_set_strv (kbd_config->settings,
+				     param_names[2], NULL);
+	}
+}
+
+/*
+ * extern MatekbdKeyboardConfig config functions
+ */
+void
+matekbd_keyboard_config_init (MatekbdKeyboardConfig * kbd_config,
+			      XklEngine * engine)
+{
+	memset (kbd_config, 0, sizeof (*kbd_config));
+	kbd_config->settings = g_settings_new (MATEKBD_KEYBOARD_CONFIG_SCHEMA);
+	kbd_config->engine = engine;
+}
+
+void
+matekbd_keyboard_config_term (MatekbdKeyboardConfig * kbd_config)
+{
+	matekbd_keyboard_config_model_set (kbd_config, NULL);
+
+	g_strfreev (kbd_config->layouts_variants);
+	kbd_config->layouts_variants = NULL;
+	g_strfreev (kbd_config->options);
+	kbd_config->options = NULL;
+
+	g_object_unref (kbd_config->settings);
+	kbd_config->settings = NULL;
+}
+
+void
+matekbd_keyboard_config_load_from_gsettings (MatekbdKeyboardConfig * kbd_config,
+				      MatekbdKeyboardConfig *
+				      kbd_config_default)
+{
+	matekbd_keyboard_config_load_params (kbd_config,
+					  MATEKBD_KEYBOARD_CONFIG_ACTIVE);
+
+	if (kbd_config_default != NULL) {
+
+		if (kbd_config->model == NULL)
+			kbd_config->model =
+			    g_strdup (kbd_config_default->model);
+
+		if (kbd_config->layouts_variants == NULL) {
+			kbd_config->layouts_variants =
+			    g_strdupv
+			    (kbd_config_default->layouts_variants);
+		}
+
+		if (kbd_config->options == NULL) {
+			kbd_config->options =
+			    g_strdupv (kbd_config_default->options);
+		}
+	}
+}
+
+void
+matekbd_keyboard_config_load_from_x_current (MatekbdKeyboardConfig * kbd_config,
+					  XklConfigRec * data)
+{
+	gboolean own_data = data == NULL;
+	xkl_debug (150, "Copying config from X(current)\n");
+	if (own_data)
+		data = xkl_config_rec_new ();
+	if (xkl_config_rec_get_from_server (data, kbd_config->engine))
+		matekbd_keyboard_config_copy_from_xkl_config (kbd_config,
+							   data);
+	else
+		xkl_debug (150,
+			   "Could not load keyboard config from server: [%s]\n",
+			   xkl_get_last_error ());
+	if (own_data)
+		g_object_unref (G_OBJECT (data));
+}
+
+void
+matekbd_keyboard_config_load_from_x_initial (MatekbdKeyboardConfig * kbd_config,
+					  XklConfigRec * data)
+{
+	gboolean own_data = data == NULL;
+	xkl_debug (150, "Copying config from X(initial)\n");
+	if (own_data)
+		data = xkl_config_rec_new ();
+	if (xkl_config_rec_get_from_backup (data, kbd_config->engine))
+		matekbd_keyboard_config_copy_from_xkl_config (kbd_config,
+							   data);
+	else
+		xkl_debug (150,
+			   "Could not load keyboard config from backup: [%s]\n",
+			   xkl_get_last_error ());
+	if (own_data)
+		g_object_unref (G_OBJECT (data));
+}
+
+static gboolean
+matekbd_keyboard_config_options_equals (MatekbdKeyboardConfig * kbd_config1,
+				     MatekbdKeyboardConfig * kbd_config2)
+{
+	int num_options, num_options2;
+
+	num_options =
+	    (kbd_config1->options ==
+	     NULL) ? 0 : g_strv_length (kbd_config1->options);
+	num_options2 =
+	    (kbd_config2->options ==
+	     NULL) ? 0 : g_strv_length (kbd_config2->options);
+
+	if (num_options != num_options2)
+		return False;
+
+	if (num_options != 0) {
+		int i;
+		char *group1, *option1;
+
+		for (i = 0; i < num_options; i++) {
+			int j;
+			char *group2, *option2;
+			gboolean are_equal = FALSE;
+
+			if (!matekbd_keyboard_config_split_items
+			    (kbd_config1->options[i], &group1, &option1))
+				continue;
+
+			option1 = g_strdup (option1);
+
+			for (j = 0; j < num_options && !are_equal; j++) {
+				if (matekbd_keyboard_config_split_items
+				    (kbd_config2->options[j], &group2,
+				     &option2)) {
+					are_equal =
+					    strcmp (option1, option2) == 0;
+				}
+			}
+
+			g_free (option1);
+
+			if (!are_equal)
+				return False;
+		}
+	}
+
+	return True;
+}
+
+gboolean
+matekbd_keyboard_config_equals (MatekbdKeyboardConfig * kbd_config1,
+			     MatekbdKeyboardConfig * kbd_config2)
+{
+	if (kbd_config1 == kbd_config2)
+		return True;
+	if ((kbd_config1->model != kbd_config2->model) &&
+	    (kbd_config1->model != NULL) &&
+	    (kbd_config2->model != NULL) &&
+	    g_ascii_strcasecmp (kbd_config1->model, kbd_config2->model))
+		return False;
+	if (!matekbd_strv_equal (kbd_config1->layouts_variants,
+			   kbd_config2->layouts_variants))
+		return False;
+
+	if (!matekbd_keyboard_config_options_equals
+	    (kbd_config1, kbd_config2))
+		return False;
+
+	return True;
+}
+
+void
+matekbd_keyboard_config_save_to_gsettings (MatekbdKeyboardConfig * kbd_config)
+{
+	g_settings_delay (kbd_config->settings);
+
+	matekbd_keyboard_config_save_params (kbd_config,
+					     MATEKBD_KEYBOARD_CONFIG_ACTIVE);
+
+	g_settings_apply (kbd_config->settings);
+}
+
+void
+matekbd_keyboard_config_model_set (MatekbdKeyboardConfig * kbd_config,
+				const gchar * model_name)
+{
+	if (kbd_config->model != NULL)
+		g_free (kbd_config->model);
+	kbd_config->model =
+	    (model_name == NULL
+	     || model_name[0] == '\0') ? NULL : g_strdup (model_name);
+}
+
+void
+matekbd_keyboard_config_options_set (MatekbdKeyboardConfig * kbd_config,
+				  gint idx,
+				  const gchar * group_name,
+				  const gchar * option_name)
+{
+	const gchar *merged;
+	if (group_name == NULL || option_name == NULL)
+		return;
+	merged =
+	    matekbd_keyboard_config_merge_items (group_name, option_name);
+	if (merged == NULL)
+		return;
+	kbd_config->options[idx] = g_strdup (merged);
+}
+
+gboolean
+matekbd_keyboard_config_options_is_set (MatekbdKeyboardConfig * kbd_config,
+				     const gchar * group_name,
+				     const gchar * option_name)
+{
+	gchar **p = kbd_config->options;
+	const gchar *merged =
+	    matekbd_keyboard_config_merge_items (group_name, option_name);
+	if (merged == NULL)
+		return FALSE;
+
+	while (p && *p) {
+		if (!g_ascii_strcasecmp (merged, *p++))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+gboolean
+matekbd_keyboard_config_activate (MatekbdKeyboardConfig * kbd_config)
+{
+	gboolean rv;
+	XklConfigRec *data = xkl_config_rec_new ();
+
+	matekbd_keyboard_config_copy_to_xkl_config (kbd_config, data);
+	rv = xkl_config_rec_activate (data, kbd_config->engine);
+	g_object_unref (G_OBJECT (data));
+
+	return rv;
+}
+
+/**
+ * matekbd_keyboard_config_start_listen:
+ * @func: (scope notified): a function to call when settings are changed
+ */
+void
+matekbd_keyboard_config_start_listen (MatekbdKeyboardConfig * kbd_config,
+				   GCallback func,
+				   gpointer user_data)
+{
+	kbd_config->config_listener_id =
+	    g_signal_connect (kbd_config->settings, "changed", func,
+			      user_data);
+}
+
+void
+matekbd_keyboard_config_stop_listen (MatekbdKeyboardConfig * kbd_config)
+{
+#if GLIB_CHECK_VERSION(2,62,0)
+	g_clear_signal_handler (&kbd_config->config_listener_id,
+	                        kbd_config->settings);
+#else
+	if (kbd_config->config_listener_id != 0) {
+		g_signal_handler_disconnect (kbd_config->settings,
+					     kbd_config->config_listener_id);
+		kbd_config->config_listener_id = 0;
+	}
+#endif
+}
+
+gboolean
+matekbd_keyboard_config_get_descriptions (XklConfigRegistry * config_registry,
+				       const gchar * name,
+				       gchar ** layout_short_descr,
+				       gchar ** layout_descr,
+				       gchar ** variant_short_descr,
+				       gchar ** variant_descr)
+{
+	char *layout_name = NULL, *variant_name = NULL;
+	if (!matekbd_keyboard_config_split_items
+	    (name, &layout_name, &variant_name))
+		return FALSE;
+	return matekbd_keyboard_config_get_lv_descriptions (config_registry,
+							 layout_name,
+							 variant_name,
+							 layout_short_descr,
+							 layout_descr,
+							 variant_short_descr,
+							 variant_descr);
+}
+
+const gchar *
+matekbd_keyboard_config_format_full_layout (const gchar * layout_descr,
+					 const gchar * variant_descr)
+{
+	static gchar full_descr[XKL_MAX_CI_DESC_LENGTH * 2];
+	if (variant_descr == NULL || variant_descr[0] == 0)
+		g_snprintf (full_descr, sizeof (full_descr), "%s",
+			    layout_descr);
+	else
+		g_snprintf (full_descr, sizeof (full_descr), "%s %s",
+			    layout_descr, variant_descr);
+	return full_descr;
+}
+
+gchar *
+matekbd_keyboard_config_to_string (const MatekbdKeyboardConfig * config)
+{
+	gchar *layouts = NULL, *options = NULL;
+	GString *buffer = g_string_new (NULL);
+
+	gchar **iter;
+	gint count;
+	gchar *result;
+
+	if (config->layouts_variants) {
+		/* g_slist_length is "expensive", so we determinate the length on the fly */
+		for (iter = config->layouts_variants, count = 0; *iter;
+		     iter++, ++count) {
+			if (buffer->len)
+				g_string_append (buffer, " ");
+
+			g_string_append (buffer, *iter);
+		}
+
+		/* Translators: The count is related to the number of options. The %s
+		 * format specifier should not be modified, left "as is". */
+		layouts =
+		    g_strdup_printf (ngettext
+				     ("layout \"%s\"", "layouts \"%s\"",
+				      count), buffer->str);
+		g_string_truncate (buffer, 0);
+	}
+	if (config->options) {
+		/* g_slist_length is "expensive", so we determinate the length on the fly */
+		for (iter = config->options, count = 0; *iter;
+		     iter++, ++count) {
+			if (buffer->len)
+				g_string_append (buffer, " ");
+
+			g_string_append (buffer, *iter);
+		}
+
+		/* Translators: The count is related to the number of options. The %s
+		 * format specifier should not be modified, left "as is". */
+		options =
+		    g_strdup_printf (ngettext
+				     ("option \"%s\"", "options \"%s\"",
+				      count), buffer->str);
+		g_string_truncate (buffer, 0);
+	}
+
+	g_string_free (buffer, TRUE);
+
+	result =
+	    g_strdup_printf (_("model \"%s\", %s and %s"), config->model,
+			     layouts ? layouts : _("no layout"),
+			     options ? options : _("no options"));
+
+	g_free (options);
+	g_free (layouts);
+
+	return result;
+}
+
+/**
+ * matekbd_keyboard_config_add_default_switch_option_if_necessary:
+ *
+ * Returns: (transfer full) (array zero-terminated=1): List of options
+ */
+gchar **
+matekbd_keyboard_config_add_default_switch_option_if_necessary (gchar **
+							        layouts_list,
+							        gchar **
+							        options_list,
+							        gboolean *was_appended)
+{
+	*was_appended = FALSE;
+	if (g_strv_length (layouts_list) >= 2) {
+		gboolean any_switcher = False;
+		if (*options_list != NULL) {
+			gchar **option = options_list;
+			while (*option != NULL) {
+				char *g, *o;
+				if (matekbd_keyboard_config_split_items
+				    (*option, &g, &o)) {
+					if (!g_ascii_strcasecmp
+					    (g, GROUP_SWITCHERS_GROUP)) {
+						any_switcher = True;
+						break;
+					}
+				}
+				option++;
+			}
+		}
+		if (!any_switcher) {
+			const gchar *id =
+			    matekbd_keyboard_config_merge_items
+			    (GROUP_SWITCHERS_GROUP,
+			     DEFAULT_GROUP_SWITCH);
+			options_list =
+			    matekbd_strv_append (options_list, g_strdup (id));
+			*was_appended = TRUE;
+		}
+	}
+	return options_list;
+}
+
+ +
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/2.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/2.html new file mode 100644 index 0000000..ed1bb9e --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/2.html @@ -0,0 +1,781 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+
  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
#include <gio/gio.h>
+
+#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+# define SECTION __attribute__ ((section (".gresource.matekbd"), aligned (8)))
+#else
+# define SECTION
+#endif
+
+static const SECTION union { const guint8 data[1061]; const double alignment; void * const ptr;}  matekbd_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, 0002, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 
+  0005, 0000, 0000, 0000, 0005, 0000, 0000, 0000, 0057, 0077, 0346, 0220, 0005, 0000, 0000, 0000, 
+  0310, 0000, 0000, 0000, 0014, 0000, 0114, 0000, 0324, 0000, 0000, 0000, 0330, 0000, 0000, 0000, 
+  0113, 0120, 0220, 0013, 0002, 0000, 0000, 0000, 0330, 0000, 0000, 0000, 0004, 0000, 0114, 0000, 
+  0334, 0000, 0000, 0000, 0340, 0000, 0000, 0000, 0324, 0265, 0002, 0000, 0377, 0377, 0377, 0377, 
+  0340, 0000, 0000, 0000, 0001, 0000, 0114, 0000, 0344, 0000, 0000, 0000, 0350, 0000, 0000, 0000, 
+  0317, 0003, 0072, 0200, 0000, 0000, 0000, 0000, 0350, 0000, 0000, 0000, 0011, 0000, 0114, 0000, 
+  0364, 0000, 0000, 0000, 0370, 0000, 0000, 0000, 0247, 0117, 0336, 0033, 0003, 0000, 0000, 0000, 
+  0370, 0000, 0000, 0000, 0016, 0000, 0166, 0000, 0010, 0001, 0000, 0000, 0031, 0004, 0000, 0000, 
+  0201, 0321, 0040, 0031, 0001, 0000, 0000, 0000, 0031, 0004, 0000, 0000, 0005, 0000, 0114, 0000, 
+  0040, 0004, 0000, 0000, 0044, 0004, 0000, 0000, 0160, 0145, 0162, 0151, 0160, 0150, 0145, 0162, 
+  0141, 0154, 0163, 0057, 0003, 0000, 0000, 0000, 0157, 0162, 0147, 0057, 0005, 0000, 0000, 0000, 
+  0057, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0153, 0145, 0171, 0142, 0157, 0141, 0162, 0144, 
+  0057, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 0163, 0150, 0157, 0167, 0055, 0154, 0141, 0171, 
+  0157, 0165, 0164, 0056, 0165, 0151, 0000, 0000, 0032, 0017, 0000, 0000, 0001, 0000, 0000, 0000, 
+  0170, 0332, 0345, 0127, 0115, 0163, 0332, 0060, 0020, 0275, 0347, 0127, 0250, 0072, 0266, 0143, 
+  0014, 0244, 0235, 0144, 0072, 0306, 0231, 0174, 0220, 0064, 0223, 0317, 0011, 0344, 0354, 0221, 
+  0355, 0005, 0124, 0024, 0311, 0225, 0004, 0011, 0235, 0376, 0370, 0112, 0066, 0041, 0020, 0004, 
+  0216, 0235, 0036, 0062, 0323, 0243, 0127, 0373, 0126, 0273, 0117, 0373, 0344, 0125, 0160, 0360, 
+  0364, 0300, 0320, 0024, 0244, 0242, 0202, 0167, 0160, 0253, 0321, 0304, 0010, 0170, 0042, 0122, 
+  0312, 0207, 0035, 0174, 0337, 0077, 0365, 0366, 0361, 0101, 0270, 0023, 0174, 0362, 0074, 0164, 
+  0006, 0034, 0044, 0321, 0220, 0242, 0107, 0252, 0107, 0150, 0310, 0110, 0012, 0150, 0267, 0321, 
+  0156, 0066, 0232, 0310, 0363, 0012, 0247, 0317, 0036, 0172, 0020, 0051, 0174, 0107, 0066, 0254, 
+  0371, 0262, 0146, 0312, 0065, 0310, 0001, 0111, 0040, 0334, 0101, 0050, 0220, 0360, 0153, 0102, 
+  0045, 0050, 0304, 0150, 0334, 0301, 0103, 0075, 0376, 0202, 0137, 0366, 0337, 0155, 0264, 0276, 
+  0142, 0077, 0367, 0023, 0361, 0117, 0110, 0064, 0112, 0030, 0121, 0252, 0203, 0317, 0364, 0370, 
+  0204, 0022, 0046, 0206, 0030, 0321, 0324, 0300, 0224, 0111, 0041, 0031, 0121, 0035, 0061, 0062, 
+  0023, 0023, 0035, 0115, 0051, 0074, 0142, 0213, 0063, 0310, 0114, 0212, 0014, 0244, 0236, 0041, 
+  0116, 0036, 0240, 0203, 0023, 0302, 0243, 0201, 0110, 0046, 0012, 0207, 0247, 0204, 0051, 0010, 
+  0374, 0147, 0007, 0267, 0177, 0054, 0144, 0012, 0062, 0172, 0244, 0251, 0036, 0341, 0360, 0133, 
+  0231, 0273, 0246, 0232, 0001, 0106, 0132, 0022, 0256, 0030, 0321, 0044, 0146, 0306, 0070, 0003, 
+  0263, 0333, 0005, 0314, 0142, 0101, 0144, 0212, 0056, 0363, 0034, 0313, 0002, 0031, 0116, 0350, 
+  0157, 0013, 0177, 0143, 0236, 0051, 0050, 0055, 0305, 0054, 0262, 0207, 0021, 0145, 0104, 0002, 
+  0327, 0070, 0354, 0313, 0111, 0051, 0120, 0317, 0062, 0210, 0106, 0324, 0272, 0247, 0071, 0247, 
+  0153, 0000, 0303, 0054, 0113, 0121, 0176, 0156, 0234, 0060, 0057, 0377, 0354, 0340, 0151, 0054, 
+  0236, 0346, 0034, 0273, 0316, 0347, 0310, 0254, 0346, 0207, 0123, 0004, 0365, 0254, 0173, 0153, 
+  0341, 0277, 0236, 0306, 0224, 0052, 0232, 0127, 0353, 0312, 0271, 0316, 0101, 0272, 0060, 0102, 
+  0122, 0303, 0013, 0321, 0246, 0273, 0160, 0150, 0332, 0114, 0323, 0204, 0260, 0267, 0000, 0125, 
+  0106, 0022, 0243, 0001, 0034, 0266, 0235, 0336, 0156, 0206, 0110, 0142, 0067, 0212, 0314, 0131, 
+  0220, 0245, 0302, 0235, 0144, 0115, 0264, 0026, 0374, 0065, 0145, 0113, 0370, 0326, 0112, 0200, 
+  0032, 0354, 0325, 0145, 0320, 0205, 0233, 0213, 0114, 0351, 0231, 0335, 0021, 0170, 0272, 0021, 
+  0230, 0023, 0261, 0152, 0333, 0134, 0176, 0121, 0173, 0254, 0371, 0255, 0314, 0273, 0361, 0025, 
+  0314, 0225, 0107, 0014, 0014, 0207, 0346, 0322, 0360, 0062, 0013, 0331, 0224, 0106, 0155, 0302, 
+  0112, 0110, 0253, 0012, 0225, 0220, 0000, 0235, 0202, 0212, 0122, 0030, 0220, 0011, 0323, 0325, 
+  0043, 0300, 0324, 0264, 0257, 0331, 0371, 0354, 0344, 0042, 0272, 0275, 0071, 0277, 0356, 0167, 
+  0357, 0242, 0253, 0233, 0376, 0371, 0315, 0165, 0164, 0165, 0330, 0273, 0100, 0177, 0220, 0143, 
+  0345, 0207, 0371, 0132, 0136, 0076, 0272, 0357, 0367, 0215, 0371, 0366, 0256, 0333, 0353, 0071, 
+  0354, 0167, 0335, 0313, 0356, 0141, 0257, 0233, 0257, 0124, 0311, 0155, 0242, 0300, 0264, 0204, 
+  0110, 0306, 0145, 0145, 0005, 0176, 0321, 0000, 0153, 0166, 0243, 0261, 0261, 0021, 0331, 0033, 
+  0150, 0170, 0312, 0010, 0117, 0253, 0323, 0067, 0240, 0214, 0125, 0107, 0145, 0102, 0321, 0342, 
+  0306, 0150, 0156, 0053, 0312, 0231, 0175, 0340, 0073, 0044, 0120, 0123, 0026, 0307, 0114, 0050, 
+  0250, 0046, 0213, 0304, 0102, 0076, 0272, 0054, 0054, 0264, 0266, 0042, 0326, 0065, 0265, 0365, 
+  0052, 0373, 0117, 0033, 0267, 0375, 0057, 0032, 0327, 0125, 0276, 0273, 0364, 0115, 0145, 0127, 
+  0372, 0313, 0024, 0065, 0127, 0202, 0330, 0144, 0042, 0073, 0317, 0154, 0377, 0053, 0125, 0325, 
+  0267, 0203, 0242, 0065, 0172, 0326, 0065, 0275, 0145, 0044, 0312, 0044, 0330, 0011, 0065, 0132, 
+  0031, 0241, 0076, 0300, 0217, 0275, 0144, 0326, 0175, 0367, 0124, 0265, 0165, 0262, 0152, 0355, 
+  0127, 0034, 0043, 0062, 0146, 0036, 0021, 0043, 0301, 0114, 0312, 0176, 0375, 0133, 0267, 0122, 
+  0224, 0367, 0113, 0240, 0312, 0061, 0226, 0253, 0176, 0163, 0053, 0267, 0352, 0266, 0362, 0152, 
+  0211, 0053, 0213, 0101, 0061, 0220, 0172, 0246, 0077, 0206, 0240, 0325, 0002, 0261, 0142, 0106, 
+  0346, 0341, 0222, 0011, 0256, 0114, 0066, 0155, 0034, 0076, 0117, 0163, 0201, 0277, 0342, 0124, 
+  0012, 0365, 0366, 0162, 0354, 0161, 0361, 0377, 0162, 0140, 0137, 0031, 0347, 0311, 0004, 0371, 
+  0114, 0272, 0210, 0236, 0113, 0157, 0116, 0315, 0342, 0215, 0350, 0025, 0343, 0253, 0227, 0277, 
+  0021, 0375, 0347, 0150, 0013, 0340, 0113, 0375, 0201, 0277, 0364, 0124, 0375, 0013, 0206, 0147, 
+  0201, 0074, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0155, 0141, 0164, 0145, 0057, 0000, 0000, 
+  0000, 0000, 0000, 0000
+} };
+
+static GStaticResource static_resource = { matekbd_resource_data.data, sizeof (matekbd_resource_data.data) - 1 /* nul terminator */, NULL, NULL, NULL };
+
+G_MODULE_EXPORT
+GResource *matekbd_get_resource (void);
+GResource *matekbd_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(matekbdresource_constructor)
+#endif
+G_DEFINE_CONSTRUCTOR(matekbdresource_constructor)
+#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(matekbdresource_destructor)
+#endif
+G_DEFINE_DESTRUCTOR(matekbdresource_destructor)
+
+#else
+#warning "Constructor not supported on this compiler, linking in resources will not work"
+#endif
+
+static void matekbdresource_constructor (void)
+{
+  g_static_resource_init (&static_resource);
+}
+
+static void matekbdresource_destructor (void)
+{
+  g_static_resource_fini (&static_resource);
+}
+
+ +
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/3.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/3.html new file mode 100644 index 0000000..facdb9b --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/3.html @@ -0,0 +1,6031 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+
   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
/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <math.h>
+#include <glib/gi18n-lib.h>
+#include <libxklavier/xklavier.h>
+
+#include <matekbd-keyboard-drawing.h>
+#include <matekbd-keyboard-drawing-marshal.h>
+#include <matekbd-util.h>
+
+#define INVALID_KEYCODE ((guint)(-1))
+
+#define GTK_RESPONSE_PRINT 2
+
+#define KEY_FONT_SIZE 12
+
+enum {
+	BAD_KEYCODE = 0,
+	NUM_SIGNALS
+};
+
+static guint matekbd_keyboard_drawing_signals[NUM_SIGNALS] = { 0 };
+
+static void matekbd_keyboard_drawing_set_mods (MatekbdKeyboardDrawing * drawing,
+					    guint mods);
+
+extern gboolean xkl_xkb_config_native_prepare (XklEngine * engine,
+					      const XklConfigRec * data,
+					      gpointer component_names);
+
+extern void xkl_xkb_config_native_cleanup (XklEngine * engine,
+					  gpointer component_names);
+
+static gint
+xkb_to_pixmap_coord (MatekbdKeyboardDrawingRenderContext * context, gint n)
+{
+	return n * context->scale_numerator / context->scale_denominator;
+}
+
+static gdouble
+xkb_to_pixmap_double (MatekbdKeyboardDrawingRenderContext * context,
+		      gdouble d)
+{
+	return d * context->scale_numerator / context->scale_denominator;
+}
+
+/* angle is in tenths of a degree; coordinates can be anything as (xkb,
+ * pixels, pango) as long as they are all the same */
+static void
+rotate_coordinate (gint origin_x,
+		   gint origin_y,
+		   gint x,
+		   gint y, gint angle, gint * rotated_x, gint * rotated_y)
+{
+	*rotated_x =
+	    origin_x + (x - origin_x) * cos (M_PI * angle / 1800.0) - (y -
+								       origin_y)
+	    * sin (M_PI * angle / 1800.0);
+	*rotated_y =
+	    origin_y + (x - origin_x) * sin (M_PI * angle / 1800.0) + (y -
+								       origin_y)
+	    * cos (M_PI * angle / 1800.0);
+}
+
+static gdouble
+length (gdouble x, gdouble y)
+{
+	return sqrt (x * x + y * y);
+}
+
+static gdouble
+point_line_distance (gdouble ax, gdouble ay, gdouble nx, gdouble ny)
+{
+	return ax * nx + ay * ny;
+}
+
+static void
+normal_form (gdouble ax, gdouble ay,
+	     gdouble bx, gdouble by,
+	     gdouble * nx, gdouble * ny, gdouble * d)
+{
+	gdouble l;
+
+	*nx = by - ay;
+	*ny = ax - bx;
+
+	l = length (*nx, *ny);
+
+	*nx /= l;
+	*ny /= l;
+
+	*d = point_line_distance (ax, ay, *nx, *ny);
+}
+
+static void
+inverse (gdouble a, gdouble b, gdouble c, gdouble d,
+	 gdouble * e, gdouble * f, gdouble * g, gdouble * h)
+{
+	gdouble det;
+
+	det = a * d - b * c;
+
+	*e = d / det;
+	*f = -b / det;
+	*g = -c / det;
+	*h = a / det;
+}
+
+static void
+multiply (gdouble a, gdouble b, gdouble c, gdouble d,
+	  gdouble e, gdouble f, gdouble * x, gdouble * y)
+{
+	*x = a * e + b * f;
+	*y = c * e + d * f;
+}
+
+static void
+intersect (gdouble n1x, gdouble n1y, gdouble d1,
+	   gdouble n2x, gdouble n2y, gdouble d2, gdouble * x, gdouble * y)
+{
+	gdouble e, f, g, h;
+
+	inverse (n1x, n1y, n2x, n2y, &e, &f, &g, &h);
+	multiply (e, f, g, h, d1, d2, x, y);
+}
+
+/* draw an angle from the current point to b and then to c,
+ * with a rounded corner of the given radius.
+ */
+static void
+rounded_corner (cairo_t * cr,
+		gdouble bx, gdouble by,
+		gdouble cx, gdouble cy, gdouble radius)
+{
+	gdouble ax, ay;
+	gdouble n1x, n1y, d1;
+	gdouble n2x, n2y, d2;
+	gdouble pd1, pd2;
+	gdouble ix, iy;
+	gdouble dist1, dist2;
+	gdouble nx, ny, d;
+	gdouble a1x, a1y, c1x, c1y;
+	gdouble phi1, phi2;
+
+	cairo_get_current_point (cr, &ax, &ay);
+#ifdef KBDRAW_DEBUG
+	printf ("        current point: (%f, %f), radius %f:\n", ax, ay,
+		radius);
+#endif
+
+	/* make sure radius is not too large */
+	dist1 = length (bx - ax, by - ay);
+	dist2 = length (cx - bx, cy - by);
+
+	radius = MIN (radius, MIN (dist1, dist2));
+
+	/* construct normal forms of the lines */
+	normal_form (ax, ay, bx, by, &n1x, &n1y, &d1);
+	normal_form (bx, by, cx, cy, &n2x, &n2y, &d2);
+
+	/* find which side of the line a,b the point c is on */
+	if (point_line_distance (cx, cy, n1x, n1y) < d1)
+		pd1 = d1 - radius;
+	else
+		pd1 = d1 + radius;
+
+	/* find which side of the line b,c the point a is on */
+	if (point_line_distance (ax, ay, n2x, n2y) < d2)
+		pd2 = d2 - radius;
+	else
+		pd2 = d2 + radius;
+
+	/* intersect the parallels to find the center of the arc */
+	intersect (n1x, n1y, pd1, n2x, n2y, pd2, &ix, &iy);
+
+	nx = (bx - ax) / dist1;
+	ny = (by - ay) / dist1;
+	d = point_line_distance (ix, iy, nx, ny);
+
+	/* a1 is the point on the line a-b where the arc starts */
+	intersect (n1x, n1y, d1, nx, ny, d, &a1x, &a1y);
+
+	nx = (cx - bx) / dist2;
+	ny = (cy - by) / dist2;
+	d = point_line_distance (ix, iy, nx, ny);
+
+	/* c1 is the point on the line b-c where the arc ends */
+	intersect (n2x, n2y, d2, nx, ny, d, &c1x, &c1y);
+
+	/* determine the first angle */
+	if (a1x - ix == 0)
+		phi1 = (a1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
+	else if (a1x - ix > 0)
+		phi1 = atan ((a1y - iy) / (a1x - ix));
+	else
+		phi1 = M_PI + atan ((a1y - iy) / (a1x - ix));
+
+	/* determine the second angle */
+	if (c1x - ix == 0)
+		phi2 = (c1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
+	else if (c1x - ix > 0)
+		phi2 = atan ((c1y - iy) / (c1x - ix));
+	else
+		phi2 = M_PI + atan ((c1y - iy) / (c1x - ix));
+
+	/* compute the difference between phi2 and phi1 mod 2pi */
+	d = phi2 - phi1;
+	while (d < 0)
+		d += 2 * M_PI;
+	while (d > 2 * M_PI)
+		d -= 2 * M_PI;
+
+#ifdef KBDRAW_DEBUG
+	printf ("        line 1 to: (%f, %f):\n", a1x, a1y);
+#endif
+	if (!(isnan (a1x) || isnan (a1y)))
+		cairo_line_to (cr, a1x, a1y);
+
+	/* pick the short arc from phi1 to phi2 */
+	if (d < M_PI)
+		cairo_arc (cr, ix, iy, radius, phi1, phi2);
+	else
+		cairo_arc_negative (cr, ix, iy, radius, phi1, phi2);
+
+#ifdef KBDRAW_DEBUG
+	printf ("        line 2 to: (%f, %f):\n", cx, cy);
+#endif
+	cairo_line_to (cr, cx, cy);
+}
+
+static void
+rounded_polygon (cairo_t * cr,
+		 gboolean filled,
+		 gdouble radius, GdkPoint * points, gint num_points)
+{
+	gint i, j;
+
+	cairo_move_to (cr,
+		       (gdouble) (points[num_points - 1].x +
+				  points[0].x) / 2,
+		       (gdouble) (points[num_points - 1].y +
+				  points[0].y) / 2);
+
+#ifdef KBDRAW_DEBUG
+	printf ("    rounded polygon of radius %f:\n", radius);
+#endif
+	for (i = 0; i < num_points; i++) {
+		j = (i + 1) % num_points;
+		rounded_corner (cr, (gdouble) points[i].x,
+				(gdouble) points[i].y,
+				(gdouble) (points[i].x + points[j].x) / 2,
+				(gdouble) (points[i].y + points[j].y) / 2,
+				radius);
+#ifdef KBDRAW_DEBUG
+		printf ("      corner (%d, %d) -> (%d, %d):\n",
+			points[i].x, points[i].y, points[j].x,
+			points[j].y);
+#endif
+	};
+	cairo_close_path (cr);
+
+	if (filled)
+		cairo_fill (cr);
+	else
+		cairo_stroke (cr);
+}
+
+static void
+draw_polygon (MatekbdKeyboardDrawingRenderContext * context,
+	      GdkRGBA * fill_color,
+	      gint xkb_x,
+	      gint xkb_y, XkbPointRec * xkb_points, guint num_points,
+	      gdouble radius)
+{
+	GdkPoint *points;
+	gboolean filled;
+	gint i;
+
+	if (fill_color) {
+		filled = TRUE;
+	} else {
+		fill_color = &context->dark_color;
+		filled = FALSE;
+	}
+
+	gdk_cairo_set_source_rgba (context->cr, fill_color);
+
+	points = g_new (GdkPoint, num_points);
+
+#ifdef KBDRAW_DEBUG
+	printf ("    Polygon points:\n");
+#endif
+	for (i = 0; i < num_points; i++) {
+		points[i].x =
+		    xkb_to_pixmap_coord (context, xkb_x + xkb_points[i].x);
+		points[i].y =
+		    xkb_to_pixmap_coord (context, xkb_y + xkb_points[i].y);
+#ifdef KBDRAW_DEBUG
+		printf ("      %d, %d\n", points[i].x, points[i].y);
+#endif
+	}
+
+	rounded_polygon (context->cr, filled,
+			 xkb_to_pixmap_double (context, radius),
+			 points, num_points);
+
+	g_free (points);
+}
+
+static void
+curve_rectangle (cairo_t * cr,
+		 gdouble x0,
+		 gdouble y0, gdouble width, gdouble height, gdouble radius)
+{
+	gdouble x1, y1;
+
+	if (!width || !height)
+		return;
+
+	x1 = x0 + width;
+	y1 = y0 + height;
+
+	radius = MIN (radius, MIN (width / 2, height / 2));
+
+	cairo_move_to (cr, x0, y0 + radius);
+	cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI,
+		   3 * M_PI / 2);
+	cairo_line_to (cr, x1 - radius, y0);
+	cairo_arc (cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2,
+		   2 * M_PI);
+	cairo_line_to (cr, x1, y1 - radius);
+	cairo_arc (cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2);
+	cairo_line_to (cr, x0 + radius, y1);
+	cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI);
+
+	cairo_close_path (cr);
+}
+
+static void
+draw_curve_rectangle (cairo_t * cr,
+		      gboolean filled,
+		      GdkRGBA * fill_color,
+		      gint x, gint y, gint width, gint height, gint radius)
+{
+	curve_rectangle (cr, x, y, width, height, radius);
+
+	gdk_cairo_set_source_rgba (cr, fill_color);
+
+	if (filled)
+		cairo_fill (cr);
+	else
+		cairo_stroke (cr);
+}
+
+/* x, y, width, height are in the xkb coordinate system */
+static void
+draw_rectangle (MatekbdKeyboardDrawingRenderContext * context,
+		GdkRGBA * fill_color,
+		gint angle,
+		gint xkb_x, gint xkb_y, gint xkb_width, gint xkb_height,
+		gint radius)
+{
+	if (angle == 0) {
+		gint x, y, width, height;
+		gboolean filled;
+
+		if (fill_color) {
+			filled = TRUE;
+		} else {
+			fill_color = &context->dark_color;
+			filled = FALSE;
+		}
+
+		x = xkb_to_pixmap_coord (context, xkb_x);
+		y = xkb_to_pixmap_coord (context, xkb_y);
+		width =
+		    xkb_to_pixmap_coord (context, xkb_x + xkb_width) - x;
+		height =
+		    xkb_to_pixmap_coord (context, xkb_y + xkb_height) - y;
+
+		draw_curve_rectangle (context->cr, filled, fill_color,
+				      x, y, width, height,
+				      xkb_to_pixmap_double (context,
+							    radius));
+	} else {
+		XkbPointRec points[4];
+		gint x, y;
+
+		points[0].x = xkb_x;
+		points[0].y = xkb_y;
+		rotate_coordinate (xkb_x, xkb_y, xkb_x + xkb_width, xkb_y,
+				   angle, &x, &y);
+		points[1].x = x;
+		points[1].y = y;
+		rotate_coordinate (xkb_x, xkb_y, xkb_x + xkb_width,
+				   xkb_y + xkb_height, angle, &x, &y);
+		points[2].x = x;
+		points[2].y = y;
+		rotate_coordinate (xkb_x, xkb_y, xkb_x, xkb_y + xkb_height,
+				   angle, &x, &y);
+		points[3].x = x;
+		points[3].y = y;
+
+		/* the points we've calculated are relative to 0,0 */
+		draw_polygon (context, fill_color, 0, 0, points, 4,
+			      radius);
+	}
+}
+
+static void
+draw_outline (MatekbdKeyboardDrawingRenderContext * context,
+	      XkbOutlineRec * outline,
+	      GdkRGBA * color,
+	      gint angle, gint origin_x, gint origin_y)
+{
+#ifdef KBDRAW_DEBUG
+	printf (" num_points in %p: %d\n", outline, outline->num_points);
+#endif
+
+	if (outline->num_points == 1) {
+		if (color)
+			draw_rectangle (context, color, angle, origin_x,
+					origin_y, outline->points[0].x,
+					outline->points[0].y,
+					outline->corner_radius);
+
+#ifdef KBDRAW_DEBUG
+		printf ("pointsxy:%d %d %d\n", outline->points[0].x,
+			outline->points[0].y, outline->corner_radius);
+#endif
+
+		draw_rectangle (context, NULL, angle, origin_x, origin_y,
+				outline->points[0].x,
+				outline->points[0].y,
+				outline->corner_radius);
+	} else if (outline->num_points == 2) {
+		gint rotated_x0, rotated_y0;
+
+		rotate_coordinate (origin_x, origin_y,
+				   origin_x + outline->points[0].x,
+				   origin_y + outline->points[0].y,
+				   angle, &rotated_x0, &rotated_y0);
+		if (color)
+			draw_rectangle (context, color, angle, rotated_x0,
+					rotated_y0, outline->points[1].x,
+					outline->points[1].y,
+					outline->corner_radius);
+
+		draw_rectangle (context, NULL, angle, rotated_x0,
+				rotated_y0, outline->points[1].x,
+				outline->points[1].y,
+				outline->corner_radius);
+	} else {
+		if (color)
+			draw_polygon (context, color, origin_x, origin_y,
+				      outline->points,
+				      outline->num_points,
+				      outline->corner_radius);
+
+		draw_polygon (context, NULL, origin_x, origin_y,
+			      outline->points, outline->num_points,
+			      outline->corner_radius);
+	}
+}
+
+/* see PSColorDef in xkbprint */
+static gboolean
+parse_xkb_color_spec (gchar * colorspec, GdkRGBA * color)
+{
+	glong level;
+
+	color->alpha = 1.0;
+
+	if (g_ascii_strcasecmp (colorspec, "black") == 0) {
+		color->red = 0;
+		color->green = 0;
+		color->blue = 0;
+	} else if (g_ascii_strcasecmp (colorspec, "white") == 0) {
+		color->red = 1.0;
+		color->green = 1.0;
+		color->blue = 1.0;
+	} else if (g_ascii_strncasecmp (colorspec, "grey", 4) == 0 ||
+		   g_ascii_strncasecmp (colorspec, "gray", 4) == 0) {
+		level = strtol (colorspec + 4, NULL, 10);
+
+		color->red = 1.0 - 1.0 * level / 100.0;
+		color->green = 1.0 - 1.0 * level / 100.0;
+		color->blue = 1.0 - 1.0 * level / 100.0;
+	} else if (g_ascii_strcasecmp (colorspec, "red") == 0) {
+		color->red = 1.0;
+		color->green = 0;
+		color->blue = 0;
+	} else if (g_ascii_strcasecmp (colorspec, "green") == 0) {
+		color->red = 0;
+		color->green = 1.0;
+		color->blue = 0;
+	} else if (g_ascii_strcasecmp (colorspec, "blue") == 0) {
+		color->red = 0;
+		color->green = 0;
+		color->blue = 1.0;
+	} else if (g_ascii_strncasecmp (colorspec, "red", 3) == 0) {
+		level = strtol (colorspec + 3, NULL, 10);
+
+		color->red = 1.0 * level / 100.0;
+		color->green = 0;
+		color->blue = 0;
+	} else if (g_ascii_strncasecmp (colorspec, "green", 5) == 0) {
+		level = strtol (colorspec + 5, NULL, 10);
+
+		color->red = 0;
+		color->green = 1.0 * level / 100.0;
+		color->blue = 0;
+	} else if (g_ascii_strncasecmp (colorspec, "blue", 4) == 0) {
+		level = strtol (colorspec + 4, NULL, 10);
+
+		color->red = 0;
+		color->green = 0;
+		color->blue = 1.0 * level / 100.0;
+	} else
+		return FALSE;
+
+	return TRUE;
+}
+
+static guint
+find_keycode (MatekbdKeyboardDrawing * drawing, gchar * key_name)
+{
+#define KEYSYM_NAME_MAX_LENGTH 4
+	guint keycode;
+	gint i, j;
+	XkbKeyNamePtr pkey;
+	XkbKeyAliasPtr palias;
+	guint is_name_matched;
+	gchar *src, *dst;
+
+	if (!drawing->xkb)
+		return INVALID_KEYCODE;
+
+#ifdef KBDRAW_DEBUG
+	printf ("    looking for keycode for (%c%c%c%c)\n",
+		key_name[0], key_name[1], key_name[2], key_name[3]);
+#endif
+
+	pkey = drawing->xkb->names->keys + drawing->xkb->min_key_code;
+	for (keycode = drawing->xkb->min_key_code;
+	     keycode <= drawing->xkb->max_key_code; keycode++) {
+		is_name_matched = 1;
+		src = key_name;
+		dst = pkey->name;
+		for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
+			if ('\0' == *src)
+				break;
+			if (*src++ != *dst++) {
+				is_name_matched = 0;
+				break;
+			}
+		}
+		if (is_name_matched) {
+#ifdef KBDRAW_DEBUG
+			printf ("      found keycode %u\n", keycode);
+#endif
+			return keycode;
+		}
+		pkey++;
+	}
+
+	palias = drawing->xkb->names->key_aliases;
+	for (j = drawing->xkb->names->num_key_aliases; --j >= 0;) {
+		is_name_matched = 1;
+		src = key_name;
+		dst = palias->alias;
+		for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
+			if ('\0' == *src)
+				break;
+			if (*src++ != *dst++) {
+				is_name_matched = 0;
+				break;
+			}
+		}
+
+		if (is_name_matched) {
+			keycode = find_keycode (drawing, palias->real);
+#ifdef KBDRAW_DEBUG
+			printf ("found alias keycode %u\n", keycode);
+#endif
+			return keycode;
+		}
+		palias++;
+	}
+
+	return INVALID_KEYCODE;
+}
+
+static void
+set_markup (MatekbdKeyboardDrawingRenderContext * context, gchar *txt)
+{
+	PangoLayout *layout = context->layout;
+	txt = strcmp ("<", txt) ? txt : "&lt;";
+	txt = strcmp ("&", txt) ? txt : "&amp;";
+	if (g_utf8_strlen (txt, -1) > 1) {
+		gchar* buf =
+		    g_strdup_printf ("<span size=\"xx-small\">%s</span>", txt);
+		pango_layout_set_markup (layout, buf, -1);
+		g_free (buf);
+	} else {
+		pango_layout_set_markup (layout, txt, -1);
+	}
+}
+
+static void
+set_key_label_in_layout (MatekbdKeyboardDrawingRenderContext * context,
+			 guint keyval)
+{
+	gchar buf[5];
+	gunichar uc;
+
+	switch (keyval) {
+	case GDK_KEY_Scroll_Lock:
+		set_markup (context, _("Scroll\nLock"));
+		break;
+
+	case GDK_KEY_space:
+		set_markup (context, "");
+		break;
+
+	case GDK_KEY_Sys_Req:
+		set_markup (context, _("Sys Rq"));
+		break;
+
+	case GDK_KEY_Page_Up:
+		set_markup (context, _("Page\nUp"));
+		break;
+
+	case GDK_KEY_Page_Down:
+		set_markup (context, _("Page\nDown"));
+		break;
+
+	case GDK_KEY_Num_Lock:
+		set_markup (context, _("Num\nLock"));
+		break;
+
+	case GDK_KEY_KP_Page_Up:
+		set_markup (context, _("Pg Up"));
+		break;
+
+	case GDK_KEY_KP_Page_Down:
+		set_markup (context, _("Pg Dn"));
+		break;
+
+	case GDK_KEY_KP_Home:
+		set_markup (context, _("Home"));
+		break;
+
+	case GDK_KEY_KP_Left:
+		set_markup (context, _("Left"));
+		break;
+
+	case GDK_KEY_KP_End:
+		set_markup (context, _("End"));
+		break;
+
+	case GDK_KEY_KP_Up:
+		set_markup (context, _("Up"));
+		break;
+
+	case GDK_KEY_KP_Begin:
+		set_markup (context, _("Begin"));
+		break;
+
+	case GDK_KEY_KP_Right:
+		set_markup (context, _("Right"));
+		break;
+
+	case GDK_KEY_KP_Enter:
+		set_markup (context, _("Enter"));
+		break;
+
+	case GDK_KEY_KP_Down:
+		set_markup (context, _("Down"));
+		break;
+
+	case GDK_KEY_KP_Insert:
+		set_markup (context, _("Ins"));
+		break;
+
+	case GDK_KEY_KP_Delete:
+		set_markup (context, _("Del"));
+		break;
+
+	/* 0xfe03 */
+	case GDK_KEY_ISO_Level3_Shift:
+		set_markup (context, _("ISO_Level3_Shift"));
+		break;
+
+	/* 0xfe20 */
+	case GDK_KEY_ISO_Left_Tab:
+		set_markup (context, _("Tab"));
+		break;
+
+	/* 0xff08 */
+	case GDK_KEY_BackSpace:
+		set_markup (context, _("BackSpace"));
+		break;
+
+	/* 0xff09 */
+	case GDK_KEY_Tab:
+		set_markup (context, _("Tab"));
+		break;
+
+	/* 0xff0d */
+	case GDK_KEY_Return:
+		set_markup (context, _("Return"));
+		break;
+
+	/* 0xff13 */
+	case GDK_KEY_Pause:
+		set_markup (context, _("Pause"));
+		break;
+
+	/* 0xff1b */
+	case GDK_KEY_Escape:
+		set_markup (context, _("Esc"));
+		break;
+
+	/* 0xff50 */
+	case GDK_KEY_Home:
+		set_markup (context, _("Home"));
+		break;
+
+	/* 0xff51 */
+	case GDK_KEY_Left:
+		set_markup (context, _("Left"));
+		break;
+
+	/* 0xff52 */
+	case GDK_KEY_Up:
+		set_markup (context, _("Up"));
+		break;
+
+	/* 0xff53 */
+	case GDK_KEY_Right:
+		set_markup (context, _("Right"));
+		break;
+
+	/* 0xff54 */
+	case GDK_KEY_Down:
+		set_markup (context, _("Down"));
+		break;
+
+	/* 0xff57 */
+	case GDK_KEY_End:
+		set_markup (context, _("End"));
+		break;
+
+	/* 0xff61 */
+	case GDK_KEY_Print:
+		set_markup (context, _("Print"));
+		break;
+
+	/* 0xff63 */
+	case GDK_KEY_Insert:
+		set_markup (context, _("Insert"));
+		break;
+
+	/* 0xff67 */
+	case GDK_KEY_Menu:
+		set_markup (context, _("Menu"));
+		break;
+
+	/* 0xffbe */
+	case GDK_KEY_F1:
+		set_markup (context, _("F1"));
+		break;
+
+	/* 0xffbf */
+	case GDK_KEY_F2:
+		set_markup (context, _("F2"));
+		break;
+
+	/* 0xffc0 */
+	case GDK_KEY_F3:
+		set_markup (context, _("F3"));
+		break;
+
+	/* 0xffc1 */
+	case GDK_KEY_F4:
+		set_markup (context, _("F4"));
+		break;
+
+	/* 0xffc2 */
+	case GDK_KEY_F5:
+		set_markup (context, _("F5"));
+		break;
+
+	/* 0xffc3 */
+	case GDK_KEY_F6:
+		set_markup (context, _("F6"));
+		break;
+
+	/* 0xffc4 */
+	case GDK_KEY_F7:
+		set_markup (context, _("F7"));
+		break;
+
+	/* 0xffc5 */
+	case GDK_KEY_F8:
+		set_markup (context, _("F8"));
+		break;
+
+	/* 0xffc6 */
+	case GDK_KEY_F9:
+		set_markup (context, _("F9"));
+		break;
+
+	/* 0xffc7 */
+	case GDK_KEY_F10:
+		set_markup (context, _("F10"));
+		break;
+
+	/* 0xffc8 */
+	case GDK_KEY_F11:
+		set_markup (context, _("F11"));
+		break;
+
+	/* 0xffc9 */
+	case GDK_KEY_F12:
+		set_markup (context, _("F12"));
+		break;
+
+	/* 0xffe1 */
+	case GDK_KEY_Shift_L:
+		set_markup (context, _("Shift"));
+		break;
+
+	/* 0xffe2 */
+	case GDK_KEY_Shift_R:
+		set_markup (context, _("Shift"));
+		break;
+
+	/* 0xffe3 */
+	case GDK_KEY_Control_L:
+		set_markup (context, _("Control"));
+		break;
+
+	/* 0xffe4 */
+	case GDK_KEY_Control_R:
+		set_markup (context, _("Control"));
+		break;
+
+	/* 0xffe5 */
+	case GDK_KEY_Caps_Lock:
+		set_markup (context, _("Caps\nLock"));
+		break;
+
+	/* 0xffe7 */
+	case GDK_KEY_Meta_L:
+		set_markup (context, _("Meta"));
+		break;
+
+	/* 0xffe9 */
+	case GDK_KEY_Alt_L:
+		set_markup (context, _("Alt"));
+		break;
+
+	/* 0xffeb */
+	case GDK_KEY_Super_L:
+		set_markup (context, _("Super"));
+		break;
+
+	/* 0xffec */
+	case GDK_KEY_Super_R:
+		set_markup (context, _("Super"));
+		break;
+
+	/* 0xffff */
+	case GDK_KEY_VoidSymbol:
+		set_markup (context, _("Delete"));
+		break;
+
+	case GDK_KEY_dead_grave:
+		set_markup (context, "ˋ");
+		break;
+
+	case GDK_KEY_dead_acute:
+		set_markup (context, "ˊ");
+		break;
+
+	case GDK_KEY_dead_circumflex:
+		set_markup (context, "ˆ");
+		break;
+
+	case GDK_KEY_dead_tilde:
+		set_markup (context, "~");
+		break;
+
+	case GDK_KEY_dead_macron:
+		set_markup (context, "ˉ");
+		break;
+
+	case GDK_KEY_dead_breve:
+		set_markup (context, "˘");
+		break;
+
+	case GDK_KEY_dead_abovedot:
+		set_markup (context, "˙");
+		break;
+
+	case GDK_KEY_dead_diaeresis:
+		set_markup (context, "¨");
+		break;
+
+	case GDK_KEY_dead_abovering:
+		set_markup (context, "˚");
+		break;
+
+	case GDK_KEY_dead_doubleacute:
+		set_markup (context, "˝");
+		break;
+
+	case GDK_KEY_dead_caron:
+		set_markup (context, "ˇ");
+		break;
+
+	case GDK_KEY_dead_cedilla:
+		set_markup (context, "¸");
+		break;
+
+	case GDK_KEY_dead_ogonek:
+		set_markup (context, "˛");
+		break;
+
+		/* case GDK_KEY_dead_iota:
+		 * case GDK_KEY_dead_voiced_sound:
+		 * case GDK_KEY_dead_semivoiced_sound: */
+
+	case GDK_KEY_dead_belowdot:
+		set_markup (context, " ̣");
+		break;
+
+	case GDK_KEY_horizconnector:
+		set_markup (context, _("horiz\nconn"));
+		break;
+
+	case GDK_KEY_Mode_switch:
+		set_markup (context, _("AltGr"));
+		break;
+
+	case GDK_KEY_Multi_key:
+		set_markup (context, _("Compose"));
+		break;
+
+	default:
+		uc = gdk_keyval_to_unicode (keyval);
+		if (uc != 0 && g_unichar_isgraph (uc)) {
+			buf[g_unichar_to_utf8 (uc, buf)] = '\0';
+			set_markup (context, buf);
+		} else {
+			gchar *name = gdk_keyval_name (keyval);
+			if (name) {
+				set_markup (context, name);
+			} else
+				set_markup (context, "");
+		}
+	}
+}
+
+static void
+draw_pango_layout (MatekbdKeyboardDrawingRenderContext * context,
+		   MatekbdKeyboardDrawing * drawing,
+		   gint angle, gint x, gint y)
+{
+	PangoLayout *layout = context->layout;
+	GdkRGBA *color;
+	PangoLayoutLine *line;
+	gint x_off, y_off;
+	gint i;
+
+	color =
+	    drawing->colors + (drawing->xkb->geom->label_color -
+			       drawing->xkb->geom->colors);
+
+	if (angle != context->angle) {
+		PangoMatrix matrix = PANGO_MATRIX_INIT;
+		pango_matrix_rotate (&matrix, -angle / 10.0);
+		pango_context_set_matrix (pango_layout_get_context
+					  (layout), &matrix);
+		pango_layout_context_changed (layout);
+		context->angle = angle;
+	}
+
+	i = 0;
+	y_off = 0;
+	for (line = pango_layout_get_line (layout, i);
+	     line != NULL; line = pango_layout_get_line (layout, ++i)) {
+		GSList *runp;
+		PangoRectangle line_extents;
+
+		x_off = 0;
+
+		for (runp = line->runs; runp != NULL; runp = runp->next) {
+			PangoGlyphItem *run = runp->data;
+			gint j;
+
+			for (j = 0; j < run->glyphs->num_glyphs; j++) {
+				PangoGlyphGeometry *geometry;
+
+				geometry =
+				    &run->glyphs->glyphs[j].geometry;
+
+				x_off += geometry->width;
+			}
+		}
+
+		pango_layout_line_get_extents (line, NULL, &line_extents);
+		y_off +=
+		    line_extents.height +
+		    pango_layout_get_spacing (layout);
+	}
+
+	cairo_move_to (context->cr, x, y);
+	gdk_cairo_set_source_rgba (context->cr, color);
+	pango_cairo_show_layout (context->cr, layout);
+}
+
+static void
+draw_key_label_helper (MatekbdKeyboardDrawingRenderContext * context,
+		       MatekbdKeyboardDrawing * drawing,
+		       KeySym keysym,
+		       gint angle,
+		       MatekbdKeyboardDrawingGroupLevelPosition glp,
+		       gint x,
+		       gint y, gint width, gint height, gint padding)
+{
+	gint label_x, label_y, label_max_width, ycell;
+
+	if (keysym == 0)
+		return;
+#ifdef KBDRAW_DEBUG
+	printf ("keysym: %04X(%c) at glp: %d\n",
+		(unsigned) keysym, (char) keysym, (int) glp);
+#endif
+
+	switch (glp) {
+	case MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT:
+	case MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT:
+		{
+			ycell =
+			    glp == MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT;
+
+			rotate_coordinate (x, y, x + padding,
+					   y + padding + (height -
+							  2 * padding) *
+					   ycell * 4 / 7, angle, &label_x,
+					   &label_y);
+			label_max_width =
+			    PANGO_SCALE * (width - 2 * padding);
+			break;
+		}
+	case MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT:
+	case MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT:
+		{
+			ycell =
+			    glp == MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT;
+
+			rotate_coordinate (x, y,
+					   x + padding + (width -
+							  2 * padding) *
+					   4 / 7,
+					   y + padding + (height -
+							  2 * padding) *
+					   ycell * 4 / 7, angle, &label_x,
+					   &label_y);
+			label_max_width =
+			    PANGO_SCALE * ((width - 2 * padding) -
+					   (width - 2 * padding) * 4 / 7);
+			break;
+		}
+	default:
+		return;
+	}
+	set_key_label_in_layout (context, keysym);
+	pango_layout_set_width (context->layout, label_max_width);
+	label_y -= (pango_layout_get_line_count (context->layout) - 1) *
+	    (pango_font_description_get_size (context->font_desc) /
+	     PANGO_SCALE);
+	cairo_save (context->cr);
+	cairo_rectangle (context->cr, x + padding / 2, y + padding / 2,
+			 width - padding, height - padding);
+	cairo_clip (context->cr);
+	draw_pango_layout (context, drawing, angle, label_x, label_y);
+	cairo_restore (context->cr);
+}
+
+static void
+draw_key_label (MatekbdKeyboardDrawingRenderContext * context,
+		MatekbdKeyboardDrawing * drawing,
+		guint keycode,
+		gint angle,
+		gint xkb_origin_x,
+		gint xkb_origin_y, gint xkb_width, gint xkb_height)
+{
+	gint x, y, width, height;
+	gint padding;
+	gint g, l, glp;
+
+	if (!drawing->xkb)
+		return;
+
+	padding = 23 * context->scale_numerator / context->scale_denominator;	/* 2.3mm */
+
+	x = xkb_to_pixmap_coord (context, xkb_origin_x);
+	y = xkb_to_pixmap_coord (context, xkb_origin_y);
+	width =
+	    xkb_to_pixmap_coord (context, xkb_origin_x + xkb_width) - x;
+	height =
+	    xkb_to_pixmap_coord (context, xkb_origin_y + xkb_height) - y;
+
+	for (glp = MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT;
+	     glp < MATEKBD_KEYBOARD_DRAWING_POS_TOTAL; glp++) {
+		if (drawing->groupLevels[glp] == NULL)
+			continue;
+		g = drawing->groupLevels[glp]->group;
+		l = drawing->groupLevels[glp]->level;
+
+		if (g < 0 || g >= XkbKeyNumGroups (drawing->xkb, keycode))
+			continue;
+		if (l < 0
+		    || l >= XkbKeyGroupWidth (drawing->xkb, keycode, g))
+			continue;
+
+		/* Skip "exotic" levels like the "Ctrl" level in PC_SYSREQ */
+		if (l > 0) {
+			guint mods = XkbKeyKeyType (drawing->xkb, keycode,
+						    g)->mods.mask;
+			if ((mods & (ShiftMask | drawing->l3mod)) == 0)
+				continue;
+		}
+
+		if (drawing->track_modifiers) {
+			guint mods_rtrn;
+			KeySym keysym;
+
+			if (XkbTranslateKeyCode (drawing->xkb, keycode,
+						 XkbBuildCoreState
+						 (drawing->mods, g),
+						 &mods_rtrn, &keysym)) {
+				draw_key_label_helper (context, drawing,
+						       keysym, angle, glp,
+						       x, y, width, height,
+						       padding);
+				/* reverse y order */
+			}
+		} else {
+			KeySym keysym;
+
+			keysym =
+			    XkbKeySymEntry (drawing->xkb, keycode, l, g);
+
+			draw_key_label_helper (context, drawing, keysym,
+					       angle, glp, x, y, width,
+					       height, padding);
+			/* reverse y order */
+		}
+	}
+}
+
+/*
+ * The x offset is calculated for complex shapes. It is the rightmost of the vertical lines in the outline
+ */
+static gint
+calc_origin_offset_x (XkbOutlineRec * outline)
+{
+	gint rv = 0;
+	gint i;
+	XkbPointPtr point = outline->points;
+	if (outline->num_points < 3)
+		return 0;
+	for (i = outline->num_points; --i > 0;) {
+		gint x1 = point->x;
+		gint y1 = point++->y;
+		gint x2 = point->x;
+		gint y2 = point->y;
+
+		/*vertical, bottom to top (clock-wise), on the left */
+		if ((x1 == x2) && (y1 > y2) && (x1 > rv)) {
+			rv = x1;
+		}
+	}
+	return rv;
+}
+
+/* groups are from 0-3 */
+static void
+draw_key (MatekbdKeyboardDrawingRenderContext * context,
+	  MatekbdKeyboardDrawing * drawing, MatekbdKeyboardDrawingKey * key)
+{
+	XkbShapeRec *shape;
+	GtkStyleContext *style_context;
+	GdkRGBA color;
+	XkbOutlineRec *outline;
+	int origin_offset_x;
+	/* gint i; */
+
+	if (!drawing->xkb)
+		return;
+
+#ifdef KBDRAW_DEBUG
+	printf ("shape: %p (base %p, index %d)\n",
+		drawing->xkb->geom->shapes + key->xkbkey->shape_ndx,
+		drawing->xkb->geom->shapes, key->xkbkey->shape_ndx);
+#endif
+
+	shape = drawing->xkb->geom->shapes + key->xkbkey->shape_ndx;
+
+	if (key->pressed) {
+		style_context = gtk_widget_get_style_context (GTK_WIDGET (drawing));
+		gtk_style_context_save (style_context);
+		gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_VIEW);
+		gtk_style_context_get_background_color (style_context,
+		                                        GTK_STATE_FLAG_SELECTED,
+		                                        &color);
+		gtk_style_context_restore (style_context);
+	 } else
+		color = *(drawing->colors + key->xkbkey->color_ndx);
+
+#ifdef KBDRAW_DEBUG
+	printf
+	    (" outlines base in the shape: %p (total: %d), origin: (%d, %d), angle %d\n",
+	     shape->outlines, shape->num_outlines, key->origin_x,
+	     key->origin_y, key->angle);
+#endif
+
+	/* draw the primary outline */
+	outline = shape->primary ? shape->primary : shape->outlines;
+	draw_outline (context, outline, &color, key->angle, key->origin_x,
+		      key->origin_y);
+#if 0
+	/* don't draw other outlines for now, since
+	 * the text placement does not take them into account
+	 */
+	for (i = 0; i < shape->num_outlines; i++) {
+		if (shape->outlines + i == shape->approx ||
+		    shape->outlines + i == shape->primary)
+			continue;
+		draw_outline (context, shape->outlines + i, NULL,
+			      key->angle, key->origin_x, key->origin_y);
+	}
+#endif
+
+	origin_offset_x = calc_origin_offset_x (outline);
+	draw_key_label (context, drawing, key->keycode, key->angle,
+			key->origin_x + origin_offset_x, key->origin_y,
+			shape->bounds.x2, shape->bounds.y2);
+}
+
+static void
+invalidate_region (MatekbdKeyboardDrawing * drawing,
+		   gdouble angle,
+		   gint origin_x, gint origin_y, XkbShapeRec * shape)
+{
+	GdkPoint points[4];
+	gint x_min, x_max, y_min, y_max;
+	gint x, y, width, height;
+	gint xx, yy;
+
+	rotate_coordinate (0, 0, 0, 0, angle, &xx, &yy);
+	points[0].x = xx;
+	points[0].y = yy;
+	rotate_coordinate (0, 0, shape->bounds.x2, 0, angle, &xx, &yy);
+	points[1].x = xx;
+	points[1].y = yy;
+	rotate_coordinate (0, 0, shape->bounds.x2, shape->bounds.y2, angle,
+			   &xx, &yy);
+	points[2].x = xx;
+	points[2].y = yy;
+	rotate_coordinate (0, 0, 0, shape->bounds.y2, angle, &xx, &yy);
+	points[3].x = xx;
+	points[3].y = yy;
+
+	x_min =
+	    MIN (MIN (points[0].x, points[1].x),
+		 MIN (points[2].x, points[3].x));
+	x_max =
+	    MAX (MAX (points[0].x, points[1].x),
+		 MAX (points[2].x, points[3].x));
+	y_min =
+	    MIN (MIN (points[0].y, points[1].y),
+		 MIN (points[2].y, points[3].y));
+	y_max =
+	    MAX (MAX (points[0].y, points[1].y),
+		 MAX (points[2].y, points[3].y));
+
+	x = xkb_to_pixmap_coord (drawing->renderContext,
+				 origin_x + x_min) - 6;
+	y = xkb_to_pixmap_coord (drawing->renderContext,
+				 origin_y + y_min) - 6;
+	width =
+	    xkb_to_pixmap_coord (drawing->renderContext,
+				 x_max - x_min) + 12;
+	height =
+	    xkb_to_pixmap_coord (drawing->renderContext,
+				 y_max - y_min) + 12;
+
+	gtk_widget_queue_draw_area (GTK_WIDGET (drawing), x, y, width,
+				    height);
+}
+
+static void
+invalidate_indicator_doodad_region (MatekbdKeyboardDrawing * drawing,
+				    MatekbdKeyboardDrawingDoodad * doodad)
+{
+	if (!drawing->xkb)
+		return;
+
+	invalidate_region (drawing,
+			   doodad->angle,
+			   doodad->origin_x +
+			   doodad->doodad->indicator.left,
+			   doodad->origin_y +
+			   doodad->doodad->indicator.top,
+			   &drawing->xkb->geom->shapes[doodad->
+						       doodad->indicator.shape_ndx]);
+}
+
+static void
+invalidate_key_region (MatekbdKeyboardDrawing * drawing,
+		       MatekbdKeyboardDrawingKey * key)
+{
+	if (!drawing->xkb)
+		return;
+
+	invalidate_region (drawing,
+			   key->angle,
+			   key->origin_x,
+			   key->origin_y,
+			   &drawing->xkb->geom->shapes[key->
+						       xkbkey->shape_ndx]);
+}
+
+static void
+draw_text_doodad (MatekbdKeyboardDrawingRenderContext * context,
+		  MatekbdKeyboardDrawing * drawing,
+		  MatekbdKeyboardDrawingDoodad * doodad,
+		  XkbTextDoodadRec * text_doodad)
+{
+	gint x, y;
+	if (!drawing->xkb)
+		return;
+
+	x = xkb_to_pixmap_coord (context,
+				 doodad->origin_x + text_doodad->left);
+	y = xkb_to_pixmap_coord (context,
+				 doodad->origin_y + text_doodad->top);
+
+	set_markup (context, text_doodad->text);
+	draw_pango_layout (context, drawing, doodad->angle, x, y);
+}
+
+static void
+draw_indicator_doodad (MatekbdKeyboardDrawingRenderContext * context,
+		       MatekbdKeyboardDrawing * drawing,
+		       MatekbdKeyboardDrawingDoodad * doodad,
+		       XkbIndicatorDoodadRec * indicator_doodad)
+{
+	GdkRGBA *color;
+	XkbShapeRec *shape;
+	gint i;
+
+	if (!drawing->xkb)
+		return;
+
+	shape = drawing->xkb->geom->shapes + indicator_doodad->shape_ndx;
+
+	color = drawing->colors + (doodad->on ?
+				   indicator_doodad->on_color_ndx :
+				   indicator_doodad->off_color_ndx);
+
+	for (i = 0; i < 1; i++)
+		draw_outline (context, shape->outlines + i, color,
+			      doodad->angle,
+			      doodad->origin_x + indicator_doodad->left,
+			      doodad->origin_y + indicator_doodad->top);
+}
+
+static void
+draw_shape_doodad (MatekbdKeyboardDrawingRenderContext * context,
+		   MatekbdKeyboardDrawing * drawing,
+		   MatekbdKeyboardDrawingDoodad * doodad,
+		   XkbShapeDoodadRec * shape_doodad)
+{
+	XkbShapeRec *shape;
+	GdkRGBA *color;
+	gint i;
+
+	if (!drawing->xkb)
+		return;
+
+	shape = drawing->xkb->geom->shapes + shape_doodad->shape_ndx;
+	color = drawing->colors + shape_doodad->color_ndx;
+
+	/* draw the primary outline filled */
+	draw_outline (context,
+		      shape->primary ? shape->primary : shape->outlines,
+		      color, doodad->angle,
+		      doodad->origin_x + shape_doodad->left,
+		      doodad->origin_y + shape_doodad->top);
+
+	/* stroke the other outlines */
+	for (i = 0; i < shape->num_outlines; i++) {
+		if (shape->outlines + i == shape->approx ||
+		    shape->outlines + i == shape->primary)
+			continue;
+		draw_outline (context, shape->outlines + i, NULL,
+			      doodad->angle,
+			      doodad->origin_x + shape_doodad->left,
+			      doodad->origin_y + shape_doodad->top);
+	}
+}
+
+static void
+draw_doodad (MatekbdKeyboardDrawingRenderContext * context,
+	     MatekbdKeyboardDrawing * drawing,
+	     MatekbdKeyboardDrawingDoodad * doodad)
+{
+	switch (doodad->doodad->any.type) {
+	case XkbOutlineDoodad:
+	case XkbSolidDoodad:
+		draw_shape_doodad (context, drawing, doodad,
+				   &doodad->doodad->shape);
+		break;
+
+	case XkbTextDoodad:
+		draw_text_doodad (context, drawing, doodad,
+				  &doodad->doodad->text);
+		break;
+
+	case XkbIndicatorDoodad:
+		draw_indicator_doodad (context, drawing, doodad,
+				       &doodad->doodad->indicator);
+		break;
+
+	case XkbLogoDoodad:
+		/* g_print ("draw_doodad: logo: %s\n", doodad->doodad->logo.logo_name); */
+		/* XkbLogoDoodadRec is essentially a subclass of XkbShapeDoodadRec */
+		draw_shape_doodad (context, drawing, doodad,
+				   &doodad->doodad->shape);
+		break;
+	}
+}
+
+typedef struct {
+	MatekbdKeyboardDrawing *drawing;
+	MatekbdKeyboardDrawingRenderContext *context;
+} DrawKeyboardItemData;
+
+static void
+redraw_overlapping_doodads (MatekbdKeyboardDrawingRenderContext * context,
+			    MatekbdKeyboardDrawing * drawing,
+			    MatekbdKeyboardDrawingKey * key)<--- Parameter 'key' can be declared as pointer to const
+{
+	GList *list;
+	gboolean do_draw = FALSE;
+
+	for (list = drawing->keyboard_items; list; list = list->next) {
+		MatekbdKeyboardDrawingItem *item = list->data;
+
+		if (do_draw
+		    && item->type ==
+		    MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD)
+			draw_doodad (context, drawing,
+				     (MatekbdKeyboardDrawingDoodad *) item);
+
+		if (list->data == key)
+			do_draw = TRUE;
+	}
+}
+
+static void
+draw_keyboard_item (MatekbdKeyboardDrawingItem * item,
+		    DrawKeyboardItemData * data)
+{
+	MatekbdKeyboardDrawing *drawing = data->drawing;
+	MatekbdKeyboardDrawingRenderContext *context = data->context;
+
+	if (!drawing->xkb)
+		return;
+
+	switch (item->type) {
+	case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID:
+		break;
+
+	case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+	case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA:
+		draw_key (context, drawing,
+			  (MatekbdKeyboardDrawingKey *) item);
+		break;
+
+	case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+		draw_doodad (context, drawing,
+			     (MatekbdKeyboardDrawingDoodad *) item);
+		break;
+	}
+}
+
+static void
+draw_keyboard_to_context (MatekbdKeyboardDrawingRenderContext * context,
+			  MatekbdKeyboardDrawing * drawing)
+{
+	DrawKeyboardItemData data = { drawing, context };
+#ifdef KBDRAW_DEBUG
+	printf ("mods: %d\n", drawing->mods);
+#endif
+	g_list_foreach (drawing->keyboard_items,
+			(GFunc) draw_keyboard_item, &data);
+}
+
+static gboolean
+create_cairo (MatekbdKeyboardDrawing * drawing)
+{
+	GtkStyleContext *style_context = NULL;
+	GtkStateFlags state;
+	GdkRGBA dark_color;
+
+	if (drawing == NULL)
+		return FALSE;
+	if (drawing->surface == NULL)
+		return FALSE;
+
+	drawing->renderContext->cr =
+	    cairo_create (drawing->surface);
+
+	style_context = gtk_widget_get_style_context (GTK_WIDGET (drawing));
+	state = gtk_style_context_get_state (style_context);
+
+	gtk_style_context_get_background_color (style_context, state,
+	                                        &dark_color);
+	/* make dark background by making regular background darker */
+	dark_color.red *= 0.7;
+	dark_color.green *= 0.7;
+	dark_color.blue *= 0.7;
+
+	drawing->renderContext->dark_color = dark_color;
+
+	return TRUE;
+}
+
+static void
+destroy_cairo (MatekbdKeyboardDrawing * drawing)
+{
+	cairo_destroy (drawing->renderContext->cr);
+	drawing->renderContext->cr = NULL;
+}
+
+static void
+draw_keyboard (MatekbdKeyboardDrawing * drawing)
+{
+        GtkStyleContext *context =
+	    gtk_widget_get_style_context (GTK_WIDGET (drawing));
+	GtkStateFlags state = gtk_style_context_get_state (context);
+	GdkRGBA color;
+	GtkAllocation allocation;
+
+	if (!drawing->xkb)
+		return;
+
+	gtk_widget_get_allocation (GTK_WIDGET (drawing), &allocation);
+
+	drawing->surface =
+	    gdk_window_create_similar_surface (gtk_widget_get_window
+					       (GTK_WIDGET (drawing)),
+					       CAIRO_CONTENT_COLOR,
+					       allocation.width,
+					       allocation.height);
+
+	if (create_cairo (drawing)) {
+		/* blank background */
+		gtk_style_context_save (context);
+		gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
+		gtk_style_context_get_background_color (context, state, &color);
+		gtk_style_context_restore (context);
+		gdk_cairo_set_source_rgba (drawing->renderContext->cr, &color);
+		cairo_paint (drawing->renderContext->cr);
+
+		draw_keyboard_to_context (drawing->renderContext, drawing);
+		destroy_cairo (drawing);
+	}
+}
+
+static void
+alloc_render_context (MatekbdKeyboardDrawing * drawing)
+{
+	MatekbdKeyboardDrawingRenderContext *context =
+	    drawing->renderContext =
+	    g_new0 (MatekbdKeyboardDrawingRenderContext, 1);
+
+	PangoContext *pangoContext =
+	    gtk_widget_get_pango_context (GTK_WIDGET (drawing));
+
+	GtkStyleContext *style_context =
+	    gtk_widget_get_style_context (GTK_WIDGET (drawing));
+
+	gtk_style_context_get (style_context,
+	                       gtk_style_context_get_state (style_context),
+	                       GTK_STYLE_PROPERTY_FONT, &context->font_desc,
+	                       NULL);
+
+	context->layout = pango_layout_new (pangoContext);
+	pango_layout_set_ellipsize (context->layout, PANGO_ELLIPSIZE_END);
+
+	context->angle = 0;
+	context->scale_numerator = 1;
+	context->scale_denominator = 1;
+}
+
+static void
+free_render_context (MatekbdKeyboardDrawing * drawing)
+{
+	MatekbdKeyboardDrawingRenderContext *context = drawing->renderContext;
+	g_object_unref (G_OBJECT (context->layout));
+	pango_font_description_free (context->font_desc);
+
+	g_free (drawing->renderContext);
+	drawing->renderContext = NULL;
+}
+
+static gboolean
+draw (GtkWidget *widget,
+      cairo_t *cr,
+      MatekbdKeyboardDrawing *drawing)
+{
+	if (!drawing->xkb)
+		return FALSE;
+
+	if (drawing->surface == NULL)
+		return FALSE;
+
+	cairo_set_source_surface (cr, drawing->surface, 0, 0);
+	cairo_paint (cr);
+
+	return FALSE;
+}
+
+static gboolean
+idle_redraw (gpointer user_data)
+{
+	MatekbdKeyboardDrawing *drawing = user_data;
+
+	drawing->idle_redraw = 0;
+	draw_keyboard (drawing);
+	gtk_widget_queue_draw (GTK_WIDGET (drawing));
+	return FALSE;
+}
+
+static gboolean
+context_setup_scaling (MatekbdKeyboardDrawingRenderContext * context,
+		       MatekbdKeyboardDrawing * drawing,
+		       gdouble width, gdouble height,
+		       gdouble dpi_x, gdouble dpi_y)
+{
+	if (!drawing->xkb)
+		return FALSE;
+
+	if (drawing->xkb->geom->width_mm <= 0
+	    || drawing->xkb->geom->height_mm <= 0) {
+		g_critical
+		    ("keyboard geometry reports width or height as zero!");
+		return FALSE;
+	}
+
+	if (width * drawing->xkb->geom->height_mm <
+	    height * drawing->xkb->geom->width_mm) {
+		context->scale_numerator = width;
+		context->scale_denominator = drawing->xkb->geom->width_mm;
+	} else {
+		context->scale_numerator = height;
+		context->scale_denominator = drawing->xkb->geom->height_mm;
+	}
+
+	pango_font_description_set_size (context->font_desc,
+					 72 * KEY_FONT_SIZE * dpi_x *
+					 context->scale_numerator /
+					 context->scale_denominator);
+	pango_layout_set_spacing (context->layout,
+				  -160 * dpi_y * context->scale_numerator /
+				  context->scale_denominator);
+	pango_layout_set_font_description (context->layout,
+					   context->font_desc);
+
+	return TRUE;
+}
+
+static void
+size_allocate (GtkWidget * widget,
+	       GtkAllocation * allocation, MatekbdKeyboardDrawing * drawing)
+{
+	MatekbdKeyboardDrawingRenderContext *context = drawing->renderContext;
+
+	if (drawing->surface) {
+		cairo_surface_destroy (drawing->surface);
+		drawing->surface = NULL;
+	}
+
+	if (!context_setup_scaling (context, drawing,
+				    allocation->width, allocation->height,
+				    50, 50))
+		return;
+
+	if (!drawing->idle_redraw)
+		drawing->idle_redraw = g_idle_add (idle_redraw, drawing);
+}
+
+static gint
+key_event (GtkWidget * widget,
+	   GdkEventKey * event, MatekbdKeyboardDrawing * drawing)
+{
+	MatekbdKeyboardDrawingKey *key;
+	if (!drawing->xkb)
+		return FALSE;
+
+	key = drawing->keys + event->hardware_keycode;
+
+	if (event->hardware_keycode > drawing->xkb->max_key_code ||
+	    event->hardware_keycode < drawing->xkb->min_key_code ||
+	    key->xkbkey == NULL) {
+		g_signal_emit (drawing,
+			       matekbd_keyboard_drawing_signals[BAD_KEYCODE],
+			       0, event->hardware_keycode);
+		return TRUE;
+	}
+
+	if ((event->type == GDK_KEY_PRESS && key->pressed) ||
+	    (event->type == GDK_KEY_RELEASE && !key->pressed))
+		return TRUE;
+	/* otherwise this event changes the state we believed we had before */
+
+	key->pressed = (event->type == GDK_KEY_PRESS);
+
+	if (create_cairo (drawing)) {
+		draw_key (drawing->renderContext, drawing, key);
+		redraw_overlapping_doodads (drawing->renderContext,
+					    drawing, key);
+		destroy_cairo (drawing);
+	}
+
+	invalidate_key_region (drawing, key);
+	return TRUE;
+}
+
+static gint
+button_press_event (GtkWidget * widget,
+		    GdkEventButton * event, MatekbdKeyboardDrawing * drawing)
+{
+	if (!drawing->xkb)
+		return FALSE;
+
+	gtk_widget_grab_focus (widget);
+	return FALSE;
+}
+
+static gboolean
+unpress_keys (MatekbdKeyboardDrawing * drawing)
+{
+	gint i;
+
+	drawing->timeout = 0;
+
+	if (!drawing->xkb)
+		return FALSE;
+
+	if (create_cairo (drawing)) {
+		for (i = drawing->xkb->min_key_code;
+		     i <= drawing->xkb->max_key_code; i++)
+			if (drawing->keys[i].pressed) {
+				drawing->keys[i].pressed = FALSE;
+				draw_key (drawing->renderContext, drawing,
+					  drawing->keys + i);
+				invalidate_key_region (drawing,
+						       drawing->keys + i);
+			}
+		destroy_cairo (drawing);
+	}
+
+	return FALSE;
+}
+
+static gint
+focus_event (GtkWidget * widget,
+	     GdkEventFocus * event, MatekbdKeyboardDrawing * drawing)
+{
+	if (event->in && drawing->timeout > 0) {
+		g_source_remove (drawing->timeout);
+		drawing->timeout = 0;
+	} else if (drawing->timeout == 0)
+		drawing->timeout =
+		    g_timeout_add (120, (GSourceFunc) unpress_keys,
+				   drawing);
+
+	return FALSE;
+}
+
+static gint
+compare_keyboard_item_priorities (MatekbdKeyboardDrawingItem * a,
+				  MatekbdKeyboardDrawingItem * b)
+{
+	if (a->priority > b->priority)
+		return 1;
+	else if (a->priority < b->priority)
+		return -1;
+	else
+		return 0;
+}
+
+static void
+init_indicator_doodad (MatekbdKeyboardDrawing * drawing,
+		       XkbDoodadRec * xkbdoodad,
+		       MatekbdKeyboardDrawingDoodad * doodad)
+{
+	if (!drawing->xkb)
+		return;
+
+	if (xkbdoodad->any.type == XkbIndicatorDoodad) {
+		gint index;
+		Atom iname = 0;
+		Atom sname = xkbdoodad->indicator.name;
+		unsigned long phys_indicators =
+		    drawing->xkb->indicators->phys_indicators;
+		Atom *pind = drawing->xkb->names->indicators;
+
+#ifdef KBDRAW_DEBUG
+		printf ("Looking for %d[%s]\n",
+			(int) sname, XGetAtomName (drawing->display,
+						   sname));
+#endif
+
+		for (index = 0; index < XkbNumIndicators; index++) {
+			iname = *pind++;
+			/* name matches and it is real */
+			if (iname == sname
+			    && (phys_indicators & (1 << index)))
+				break;
+			if (iname == 0)
+				break;
+		}
+		if (iname == 0)
+			g_warning ("Could not find indicator %d [%s]\n",
+				   (int) sname,
+				   XGetAtomName (drawing->display, sname));
+		else {
+#ifdef KBDRAW_DEBUG
+			printf ("Found in xkbdesc as %d\n", index);
+#endif
+			drawing->physical_indicators[index] = doodad;
+			/* Trying to obtain the real state, but if fail - just assume OFF */
+			if (!XkbGetNamedIndicator
+			    (drawing->display, sname, NULL, &doodad->on,
+			     NULL, NULL))
+				doodad->on = 0;
+		}
+	}
+}
+
+static void
+init_keys_and_doodads (MatekbdKeyboardDrawing * drawing)
+{
+	gint i, j, k;
+	gint x, y;
+
+	if (!drawing->xkb)
+		return;
+
+	for (i = 0; i < drawing->xkb->geom->num_doodads; i++) {
+		XkbDoodadRec *xkbdoodad = drawing->xkb->geom->doodads + i;
+		MatekbdKeyboardDrawingDoodad *doodad =
+		    g_new (MatekbdKeyboardDrawingDoodad, 1);
+
+		doodad->type = MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD;
+		doodad->origin_x = 0;
+		doodad->origin_y = 0;
+		doodad->angle = 0;
+		doodad->priority = xkbdoodad->any.priority * 256 * 256;
+		doodad->doodad = xkbdoodad;
+
+		init_indicator_doodad (drawing, xkbdoodad, doodad);
+
+		drawing->keyboard_items =
+		    g_list_append (drawing->keyboard_items, doodad);
+	}
+
+	for (i = 0; i < drawing->xkb->geom->num_sections; i++) {
+		XkbSectionRec *section = drawing->xkb->geom->sections + i;
+		guint priority;
+
+#ifdef KBDRAW_DEBUG
+		printf ("initing section %d containing %d rows\n", i,
+			section->num_rows);
+#endif
+		x = section->left;
+		y = section->top;
+		priority = section->priority * 256 * 256;
+
+		for (j = 0; j < section->num_rows; j++) {
+			XkbRowRec *row = section->rows + j;
+
+#ifdef KBDRAW_DEBUG
+			printf ("  initing row %d\n", j);
+#endif
+			x = section->left + row->left;
+			y = section->top + row->top;
+
+			for (k = 0; k < row->num_keys; k++) {
+				XkbKeyRec *xkbkey = row->keys + k;
+				MatekbdKeyboardDrawingKey *key;
+				XkbShapeRec *shape =
+				    drawing->xkb->geom->shapes +
+				    xkbkey->shape_ndx;
+				guint keycode = find_keycode (drawing,
+							      xkbkey->
+							      name.name);
+
+				if (keycode == INVALID_KEYCODE)
+					continue;
+#ifdef KBDRAW_DEBUG
+				printf
+				    ("    initing key %d, shape: %p(%p + %d), code: %u\n",
+				     k, shape, drawing->xkb->geom->shapes,
+				     xkbkey->shape_ndx, keycode);
+#endif
+				if (row->vertical)
+					y += xkbkey->gap;
+				else
+					x += xkbkey->gap;
+
+				if (keycode >= drawing->xkb->min_key_code
+				    && keycode <=
+				    drawing->xkb->max_key_code) {
+					key = drawing->keys + keycode;
+					if (key->type ==
+					    MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID)
+					{
+						key->type =
+						    MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY;
+					} else {
+						/* duplicate key for the same keycode,
+						   already defined as MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY */
+						key =
+						    g_new0
+						    (MatekbdKeyboardDrawingKey,
+						     1);
+						key->type =
+						    MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA;
+					}
+				} else {
+					g_warning
+					    ("key %4.4s: keycode = %u; not in range %d..%d\n",
+					     xkbkey->name.name, keycode,
+					     drawing->xkb->min_key_code,
+					     drawing->xkb->max_key_code);
+
+					key =
+					    g_new0 (MatekbdKeyboardDrawingKey,
+						    1);
+					key->type =
+					    MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA;
+				}
+
+				key->xkbkey = xkbkey;
+				key->angle = section->angle;
+				rotate_coordinate (section->left,
+						   section->top, x, y,
+						   section->angle,
+						   &key->origin_x,
+						   &key->origin_y);
+				key->priority = priority;
+				key->keycode = keycode;
+
+				drawing->keyboard_items =
+				    g_list_append (drawing->keyboard_items,
+						   key);
+
+				if (row->vertical)
+					y += shape->bounds.y2;
+				else
+					x += shape->bounds.x2;
+
+				priority++;
+			}
+		}
+
+		for (j = 0; j < section->num_doodads; j++) {
+			XkbDoodadRec *xkbdoodad = section->doodads + j;
+			MatekbdKeyboardDrawingDoodad *doodad =
+			    g_new (MatekbdKeyboardDrawingDoodad, 1);
+
+			doodad->type =
+			    MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD;
+			doodad->origin_x = x;
+			doodad->origin_y = y;
+			doodad->angle = section->angle;
+			doodad->priority =
+			    priority + xkbdoodad->any.priority;
+			doodad->doodad = xkbdoodad;
+
+			init_indicator_doodad (drawing, xkbdoodad, doodad);
+
+			drawing->keyboard_items =
+			    g_list_append (drawing->keyboard_items,
+					   doodad);
+		}
+	}
+
+	drawing->keyboard_items = g_list_sort (drawing->keyboard_items,
+					       (GCompareFunc)
+					       compare_keyboard_item_priorities);
+}
+
+static void
+init_colors (MatekbdKeyboardDrawing * drawing)
+{
+	gboolean result;
+	gint i;
+
+	if (!drawing->xkb)
+		return;
+
+	drawing->colors = g_new (GdkRGBA, drawing->xkb->geom->num_colors);
+
+	for (i = 0; i < drawing->xkb->geom->num_colors; i++) {
+		result =
+		    parse_xkb_color_spec (drawing->xkb->geom->
+					  colors[i].spec,
+					  drawing->colors + i);
+
+		if (!result)
+			g_warning
+			    ("init_colors: unable to parse color %s\n",
+			     drawing->xkb->geom->colors[i].spec);
+	}
+}
+
+static void
+free_cdik (			/*colors doodads indicators keys */
+		  MatekbdKeyboardDrawing * drawing)
+{
+	GList *itemp;
+
+	if (!drawing->xkb)
+		return;
+
+	for (itemp = drawing->keyboard_items; itemp; itemp = itemp->next) {
+		MatekbdKeyboardDrawingItem *item = itemp->data;
+
+		switch (item->type) {
+		case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID:
+		case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+			break;
+
+		case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA:
+		case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+			g_free (item);
+			break;
+		}
+	}
+
+	g_list_free (drawing->keyboard_items);
+	drawing->keyboard_items = NULL;
+
+	g_free (drawing->physical_indicators);
+	g_free (drawing->keys);
+	g_free (drawing->colors);
+}
+
+static void
+alloc_cdik (MatekbdKeyboardDrawing * drawing)
+{
+	if (!drawing->xkb)
+		return;
+
+	drawing->physical_indicators_size =
+	    drawing->xkb->indicators->phys_indicators + 1;
+	drawing->physical_indicators =
+	    g_new0 (MatekbdKeyboardDrawingDoodad *,
+		    drawing->physical_indicators_size);
+	drawing->keys =
+	    g_new0 (MatekbdKeyboardDrawingKey,
+		    drawing->xkb->max_key_code + 1);
+}
+
+static void
+process_indicators_state_notify (XkbIndicatorNotifyEvent * iev,
+				 MatekbdKeyboardDrawing * drawing)
+{
+	/* Good question: should we track indicators when the keyboard is
+	   NOT really taken from the screen */
+	gint i;
+
+	for (i = 0; i <= drawing->xkb->indicators->phys_indicators; i++)
+		if (drawing->physical_indicators[i] != NULL
+		    && (iev->changed & 1 << i)) {
+			gint state = (iev->state & 1 << i) != FALSE;
+
+			if ((state && !drawing->physical_indicators[i]->on)
+			    || (!state
+				&& drawing->physical_indicators[i]->on)) {
+				drawing->physical_indicators[i]->on =
+				    state;
+				if (create_cairo (drawing)) {
+					draw_doodad
+					    (drawing->renderContext,
+					     drawing,
+					     drawing->physical_indicators
+					     [i]);
+					destroy_cairo (drawing);
+				}
+				invalidate_indicator_doodad_region
+				    (drawing,
+				     drawing->physical_indicators[i]);
+			}
+		}
+}
+
+static GdkFilterReturn
+xkb_state_notify_event_filter (GdkXEvent * gdkxev,
+			       GdkEvent * event,
+			       MatekbdKeyboardDrawing * drawing)
+{
+#define modifier_change_mask (XkbModifierStateMask | XkbModifierBaseMask | XkbModifierLatchMask | XkbModifierLockMask)
+
+	if (!drawing->xkb)
+		return GDK_FILTER_CONTINUE;
+
+	if (((XEvent *) gdkxev)->type == drawing->xkb_event_type) {
+		XkbEvent *kev = (XkbEvent *) gdkxev;
+		GtkAllocation allocation;
+		switch (kev->any.xkb_type) {
+		case XkbStateNotify:
+			if (((kev->state.changed & modifier_change_mask) &&
+			     drawing->track_modifiers)) {
+				free_cdik (drawing);
+				if (drawing->track_modifiers)
+					matekbd_keyboard_drawing_set_mods
+					    (drawing,
+					     kev->state.compat_state);
+				drawing->keys =
+				    g_new0 (MatekbdKeyboardDrawingKey,
+					    drawing->xkb->max_key_code +
+					    1);
+
+				gtk_widget_get_allocation (GTK_WIDGET
+							   (drawing),
+							   &allocation);
+				size_allocate (GTK_WIDGET (drawing),
+					       &allocation, drawing);
+
+				init_keys_and_doodads (drawing);
+				init_colors (drawing);
+			}
+			break;
+
+		case XkbIndicatorStateNotify:
+			{
+				process_indicators_state_notify (&
+								 ((XkbEvent
+								   *)
+								  gdkxev)->indicators,
+drawing);
+			}
+			break;
+
+		case XkbIndicatorMapNotify:
+		case XkbControlsNotify:
+		case XkbNamesNotify:
+		case XkbNewKeyboardNotify:
+			{
+				XkbStateRec state;
+				memset (&state, 0, sizeof (state));
+				XkbGetState (drawing->display,
+					     XkbUseCoreKbd, &state);
+				if (drawing->track_modifiers)
+					matekbd_keyboard_drawing_set_mods
+					    (drawing, state.compat_state);
+				if (drawing->track_config)
+					matekbd_keyboard_drawing_set_keyboard
+					    (drawing, NULL);
+			}
+			break;
+		}
+	}
+
+	return GDK_FILTER_CONTINUE;
+}
+
+static void
+destroy (MatekbdKeyboardDrawing * drawing)
+{
+	free_render_context (drawing);
+	gdk_window_remove_filter (NULL, (GdkFilterFunc)
+				  xkb_state_notify_event_filter, drawing);
+	if (drawing->timeout > 0) {
+		g_source_remove (drawing->timeout);
+		drawing->timeout = 0;
+	}
+	if (drawing->idle_redraw > 0) {
+		g_source_remove (drawing->idle_redraw);
+		drawing->idle_redraw = 0;
+	}
+
+	if (drawing->surface != NULL) {
+		cairo_surface_destroy (drawing->surface);
+	}
+
+	free_cdik (drawing);
+}
+
+static void
+style_changed (MatekbdKeyboardDrawing * drawing)
+{
+	pango_layout_context_changed (drawing->renderContext->layout);
+}
+
+static void
+matekbd_keyboard_drawing_init (MatekbdKeyboardDrawing * drawing)
+{
+	gint opcode = 0, error = 0, major = 1, minor = 0;
+	gint mask;
+
+	drawing->display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+
+	printf ("dpy: %p\n", (void *) drawing->display);
+
+	if (!XkbQueryExtension
+	    (drawing->display, &opcode, &drawing->xkb_event_type, &error,
+	     &major, &minor))
+		g_critical
+		    ("XkbQueryExtension failed! Stuff probably won't work.");
+
+	printf ("evt/error/major/minor: %d/%d/%d/%d\n",
+		drawing->xkb_event_type, error, major, minor);
+
+	/* XXX: this stuff probably doesn't matter.. also, gdk_screen_get_default can fail */
+	if (gtk_widget_has_screen (GTK_WIDGET (drawing)))
+		drawing->screen_num =
+		    gdk_x11_screen_get_screen_number (gtk_widget_get_screen
+					   (GTK_WIDGET (drawing)));
+	else
+		drawing->screen_num =
+		    gdk_x11_screen_get_screen_number (gdk_screen_get_default ());
+
+	drawing->surface = NULL;
+	alloc_render_context (drawing);
+
+	drawing->keyboard_items = NULL;
+	drawing->colors = NULL;
+
+	drawing->track_modifiers = 0;
+	drawing->track_config = 0;
+
+	/* XXX: XkbClientMapMask | XkbIndicatorMapMask | XkbNamesMask | XkbGeometryMask */
+	drawing->xkb = XkbGetKeyboard (drawing->display,
+				       XkbGBN_GeometryMask |
+				       XkbGBN_KeyNamesMask |
+				       XkbGBN_OtherNamesMask |
+				       XkbGBN_SymbolsMask |
+				       XkbGBN_IndicatorMapMask,
+				       XkbUseCoreKbd);
+	if (drawing->xkb) {
+		XkbGetNames (drawing->display, XkbAllNamesMask, drawing->xkb);
+		XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+				       XkbIndicatorStateNotify,
+				       drawing->xkb->indicators->phys_indicators,
+				       drawing->xkb->indicators->phys_indicators);
+	}
+
+	drawing->l3mod = XkbKeysymToModifiers (drawing->display,
+					       GDK_KEY_ISO_Level3_Shift);
+
+	drawing->xkbOnDisplay = TRUE;
+
+	alloc_cdik (drawing);
+
+	mask =
+	    (XkbStateNotifyMask | XkbNamesNotifyMask |
+	     XkbControlsNotifyMask | XkbIndicatorMapNotifyMask |
+	     XkbNewKeyboardNotifyMask);
+	XkbSelectEvents (drawing->display, XkbUseCoreKbd, mask, mask);
+
+	mask = XkbGroupStateMask | XkbModifierStateMask;
+	XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+			       XkbStateNotify, mask, mask);
+
+	mask = (XkbGroupNamesMask | XkbIndicatorNamesMask);
+	XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+			       XkbNamesNotify, mask, mask);
+	init_keys_and_doodads (drawing);
+	init_colors (drawing);
+
+	/* required to get key events */
+	gtk_widget_set_can_focus (GTK_WIDGET (drawing), TRUE);
+
+	gtk_widget_set_events (GTK_WIDGET (drawing),
+			       GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
+			       GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK
+			       | GDK_FOCUS_CHANGE_MASK);
+	g_signal_connect (G_OBJECT (drawing), "draw",
+			  G_CALLBACK (draw), drawing);
+	g_signal_connect_after (G_OBJECT (drawing), "key-press-event",
+				G_CALLBACK (key_event), drawing);
+	g_signal_connect_after (G_OBJECT (drawing), "key-release-event",
+				G_CALLBACK (key_event), drawing);
+	g_signal_connect (G_OBJECT (drawing), "button-press-event",
+			  G_CALLBACK (button_press_event), drawing);
+	g_signal_connect (G_OBJECT (drawing), "focus-out-event",
+			  G_CALLBACK (focus_event), drawing);
+	g_signal_connect (G_OBJECT (drawing), "focus-in-event",
+			  G_CALLBACK (focus_event), drawing);
+	g_signal_connect (G_OBJECT (drawing), "size-allocate",
+			  G_CALLBACK (size_allocate), drawing);
+	g_signal_connect (G_OBJECT (drawing), "destroy",
+			  G_CALLBACK (destroy), drawing);
+	g_signal_connect (G_OBJECT (drawing), "style-set",
+			  G_CALLBACK (style_changed), drawing);
+
+	gdk_window_add_filter (NULL, (GdkFilterFunc)
+			       xkb_state_notify_event_filter, drawing);
+}
+
+GtkWidget *
+matekbd_keyboard_drawing_new (void)
+{
+	return
+	    GTK_WIDGET (g_object_new
+			(matekbd_keyboard_drawing_get_type (), NULL));
+}
+
+static void
+matekbd_keyboard_drawing_class_init (MatekbdKeyboardDrawingClass * klass)
+{
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+	gtk_widget_class_set_css_name (widget_class, "matekbd-keyboard-drawing");
+
+	klass->bad_keycode = NULL;
+
+	matekbd_keyboard_drawing_signals[BAD_KEYCODE] =
+	    g_signal_new ("bad-keycode", matekbd_keyboard_drawing_get_type (),
+			  G_SIGNAL_RUN_FIRST,
+			  G_STRUCT_OFFSET (MatekbdKeyboardDrawingClass,
+					   bad_keycode), NULL, NULL,
+			  matekbd_keyboard_drawing_VOID__UINT, G_TYPE_NONE, 1,
+			  G_TYPE_UINT);
+}
+
+GType
+matekbd_keyboard_drawing_get_type (void)
+{
+	static GType matekbd_keyboard_drawing_type = 0;
+
+	if (!matekbd_keyboard_drawing_type) {
+		static const GTypeInfo matekbd_keyboard_drawing_info = {
+			sizeof (MatekbdKeyboardDrawingClass),
+			NULL,	/* base_init */
+			NULL,	/* base_finalize */
+			(GClassInitFunc) matekbd_keyboard_drawing_class_init,
+			NULL,	/* class_finalize */
+			NULL,	/* class_data */
+			sizeof (MatekbdKeyboardDrawing),
+			0,	/* n_preallocs */
+			(GInstanceInitFunc) matekbd_keyboard_drawing_init,
+			NULL	/* *value_table */
+		};
+
+		matekbd_keyboard_drawing_type =
+		    g_type_register_static (GTK_TYPE_DRAWING_AREA,
+					    "MatekbdKeyboardDrawing",
+					    &matekbd_keyboard_drawing_info,
+					    0);
+	}
+
+	return matekbd_keyboard_drawing_type;
+}
+
+void
+matekbd_keyboard_drawing_set_mods (MatekbdKeyboardDrawing * drawing, guint mods)
+{
+#ifdef KBDRAW_DEBUG
+	printf ("set_mods: %d\n", mods);
+#endif
+	if (mods != drawing->mods) {
+		drawing->mods = mods;
+		gtk_widget_queue_draw (GTK_WIDGET (drawing));
+	}
+}
+
+/**
+ * matekbd_keyboard_drawing_render:
+ * @kbdrawing: keyboard layout to render
+ * @cr:        Cairo context to render to
+ * @layout:    Pango layout to use to render text
+ * @x:         left coordinate (pixels) of region to render in
+ * @y:         top coordinate (pixels) of region to render in
+ * @width:     width (pixels) of region to render in
+ * @height:    height (pixels) of region to render in
+ *
+ * Renders a keyboard layout to a cairo_t context.  @cr and @layout can be got
+ * from e.g. a GtkWidget or a GtkPrintContext.  @cr and @layout may be modified
+ * by the function but will not be unreffed.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ */
+gboolean
+matekbd_keyboard_drawing_render (MatekbdKeyboardDrawing * kbdrawing,
+			      cairo_t * cr,
+			      PangoLayout * layout,
+			      double x, double y,
+			      double width, double height,
+			      double dpi_x, double dpi_y)
+{
+	GtkStyleContext *style_context =
+	    gtk_widget_get_style_context (GTK_WIDGET (kbdrawing));
+	GdkRGBA dark_color;
+	PangoFontDescription *fd;
+
+	gtk_style_context_get_background_color (style_context,
+	                                        gtk_style_context_get_state (style_context),
+	                                        &dark_color);
+	/* make dark background by making regular background darker */
+	dark_color.red *= 0.7;
+	dark_color.green *= 0.7;
+	dark_color.blue *= 0.7;
+
+	gtk_style_context_get (style_context,
+	                       gtk_style_context_get_state (style_context),
+	                       GTK_STYLE_PROPERTY_FONT, &fd,
+	                       NULL);
+
+	MatekbdKeyboardDrawingRenderContext context = {
+		cr,
+		kbdrawing->renderContext->angle,
+		layout,
+		fd,
+		1, 1,
+		dark_color
+	};
+
+	if (!context_setup_scaling (&context, kbdrawing, width, height,
+	                            dpi_x, dpi_y))
+	{
+		pango_font_description_free (fd);
+		return FALSE;
+	}
+
+	cairo_translate (cr, x, y);
+
+	draw_keyboard_to_context (&context, kbdrawing);
+
+	pango_font_description_free (fd);
+
+	return TRUE;
+}
+
+/**
+ * matekbd_keyboard_drawing_set_keyboard: (skip)
+ */
+gboolean
+matekbd_keyboard_drawing_set_keyboard (MatekbdKeyboardDrawing * drawing,
+				    XkbComponentNamesRec * names)
+{
+	GtkAllocation allocation;
+
+	free_cdik (drawing);
+	if (drawing->xkb)
+		XkbFreeKeyboard (drawing->xkb, 0, TRUE);	/* free_all = TRUE */
+	drawing->xkb = NULL;
+
+	if (names) {
+		drawing->xkb =
+		    XkbGetKeyboardByName (drawing->display, XkbUseCoreKbd,
+					  names, 0,
+					  XkbGBN_GeometryMask |
+					  XkbGBN_KeyNamesMask |
+					  XkbGBN_OtherNamesMask |
+					  XkbGBN_ClientSymbolsMask |
+					  XkbGBN_IndicatorMapMask, FALSE);
+		drawing->xkbOnDisplay = FALSE;
+	} else {
+		drawing->xkb = XkbGetKeyboard (drawing->display,
+					       XkbGBN_GeometryMask |
+					       XkbGBN_KeyNamesMask |
+					       XkbGBN_OtherNamesMask |
+					       XkbGBN_SymbolsMask |
+					       XkbGBN_IndicatorMapMask,
+					       XkbUseCoreKbd);
+		XkbGetNames (drawing->display, XkbAllNamesMask,
+			     drawing->xkb);
+		drawing->xkbOnDisplay = TRUE;
+	}
+
+	if (drawing->xkb) {
+		XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+				       XkbIndicatorStateNotify,
+				       drawing->xkb->indicators->phys_indicators,
+				       drawing->xkb->indicators->phys_indicators);
+	}
+
+	alloc_cdik (drawing);
+
+	init_keys_and_doodads (drawing);
+	init_colors (drawing);
+
+	gtk_widget_get_allocation (GTK_WIDGET (drawing), &allocation);
+	size_allocate (GTK_WIDGET (drawing), &allocation, drawing);
+	gtk_widget_queue_draw (GTK_WIDGET (drawing));
+
+	return TRUE;
+}
+
+const gchar* matekbd_keyboard_drawing_get_keycodes(MatekbdKeyboardDrawing* drawing)
+{
+	if (!drawing->xkb || drawing->xkb->names->keycodes <= 0)
+	{
+		return NULL;
+	}
+	else
+	{
+		return XGetAtomName(drawing->display, drawing->xkb->names->keycodes);
+	}
+}
+
+const gchar* matekbd_keyboard_drawing_get_geometry(MatekbdKeyboardDrawing* drawing)
+{
+	if (!drawing->xkb || drawing->xkb->names->geometry <= 0)
+	{
+		return NULL;
+	}
+	else
+	{
+		return XGetAtomName(drawing->display, drawing->xkb->names->geometry);
+	}
+}
+
+const gchar* matekbd_keyboard_drawing_get_symbols(MatekbdKeyboardDrawing* drawing)
+{
+	if (!drawing->xkb || drawing->xkb->names->symbols <= 0)
+	{
+		return NULL;
+	}
+	else
+	{
+		return XGetAtomName(drawing->display, drawing->xkb->names->symbols);
+	}
+}
+
+const gchar* matekbd_keyboard_drawing_get_types(MatekbdKeyboardDrawing* drawing)
+{
+	if (!drawing->xkb || drawing->xkb->names->types <= 0)
+	{
+		return NULL;
+	}
+	else
+	{
+		return XGetAtomName(drawing->display, drawing->xkb->names->types);
+	}
+}
+
+const gchar* matekbd_keyboard_drawing_get_compat(MatekbdKeyboardDrawing* drawing)
+{
+	if (!drawing->xkb || drawing->xkb->names->compat <= 0)
+	{
+		return NULL;
+	}
+	else
+	{
+		return XGetAtomName(drawing->display, drawing->xkb->names->compat);
+	}
+}
+
+void
+matekbd_keyboard_drawing_set_track_modifiers (MatekbdKeyboardDrawing * drawing,
+					   gboolean enable)
+{
+	if (enable) {
+		XkbStateRec state;
+		drawing->track_modifiers = 1;
+		memset (&state, 0, sizeof (state));
+		XkbGetState (drawing->display, XkbUseCoreKbd, &state);
+		matekbd_keyboard_drawing_set_mods (drawing,
+						state.compat_state);
+	} else
+		drawing->track_modifiers = 0;
+}
+
+void
+matekbd_keyboard_drawing_set_track_config (MatekbdKeyboardDrawing * drawing,
+					gboolean enable)
+{
+	if (enable)
+		drawing->track_config = 1;
+	else
+		drawing->track_config = 0;
+}
+
+void
+matekbd_keyboard_drawing_set_groups_levels (MatekbdKeyboardDrawing * drawing,
+					 MatekbdKeyboardDrawingGroupLevel *
+					 groupLevels[])
+{
+#ifdef KBDRAW_DEBUG
+	printf ("set_group_levels [topLeft]: %d %d \n",
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT]->group,
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT]->level);
+	printf ("set_group_levels [topRight]: %d %d \n",
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT]->group,
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT]->level);
+	printf ("set_group_levels [bottomLeft]: %d %d \n",
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->group,
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->level);
+	printf ("set_group_levels [bottomRight]: %d %d \n",
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->group,
+		groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->level);
+#endif
+	drawing->groupLevels = groupLevels;
+
+	gtk_widget_queue_draw (GTK_WIDGET (drawing));
+}
+
+typedef struct {
+	MatekbdKeyboardDrawing *drawing;
+	const gchar *description;
+} XkbLayoutPreviewPrintData;
+
+static void
+matekbd_keyboard_drawing_begin_print (GtkPrintOperation * operation,
+				   GtkPrintContext * context,
+				   XkbLayoutPreviewPrintData * data)
+{
+	/* We always print single-page documents */
+	GtkPrintSettings *settings =
+	    gtk_print_operation_get_print_settings (operation);
+	gtk_print_operation_set_n_pages (operation, 1);
+	if (!gtk_print_settings_has_key
+	    (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+		gtk_print_settings_set_orientation (settings,
+						    GTK_PAGE_ORIENTATION_LANDSCAPE);
+}
+
+static void
+matekbd_keyboard_drawing_draw_page (GtkPrintOperation * operation,
+				 GtkPrintContext * context,
+				 gint page_nr,
+				 XkbLayoutPreviewPrintData * data)
+{
+	cairo_t *cr = gtk_print_context_get_cairo_context (context);
+	PangoLayout *layout =
+	    gtk_print_context_create_pango_layout (context);
+	PangoFontDescription *desc =
+	    pango_font_description_from_string ("sans 8");
+	gdouble width = gtk_print_context_get_width (context);
+	gdouble height = gtk_print_context_get_height (context);
+	gdouble dpi_x = gtk_print_context_get_dpi_x (context);
+	gdouble dpi_y = gtk_print_context_get_dpi_y (context);
+	gchar *header;
+
+	gtk_print_operation_set_unit (operation, GTK_UNIT_PIXEL);
+
+	header = g_strdup_printf
+	    (_("Keyboard layout \"%s\"\n"
+	       "Copyright &#169; X.Org Foundation and "
+	       "XKeyboardConfig contributors\n"
+	       "For licensing see package metadata"), data->description);
+	pango_layout_set_markup (layout, header, -1);
+	pango_layout_set_font_description (layout, desc);
+	pango_font_description_free (desc);
+	pango_layout_set_width (layout, pango_units_from_double (width));
+	pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+	cairo_set_source_rgb (cr, 0, 0, 0);
+	cairo_move_to (cr, 0, 0);
+	pango_cairo_show_layout (cr, layout);
+
+	matekbd_keyboard_drawing_render (MATEKBD_KEYBOARD_DRAWING
+				      (data->drawing), cr, layout, 0.0,
+				      0.0, width, height, dpi_x, dpi_y);
+
+	g_object_unref (layout);
+}
+
+void
+matekbd_keyboard_drawing_print (MatekbdKeyboardDrawing * drawing,
+			     GtkWindow * parent_window,
+			     const gchar * description)
+{
+	GtkPrintOperation *print;
+	GtkPrintOperationResult res;
+	static GtkPrintSettings *settings = NULL;
+	XkbLayoutPreviewPrintData data = { drawing, description };
+
+	print = gtk_print_operation_new ();
+
+	if (settings != NULL)
+		gtk_print_operation_set_print_settings (print, settings);
+
+	g_signal_connect (print, "begin_print",
+			  G_CALLBACK (matekbd_keyboard_drawing_begin_print),
+			  &data);
+	g_signal_connect (print, "draw_page",
+			  G_CALLBACK (matekbd_keyboard_drawing_draw_page),
+			  &data);
+
+	res = gtk_print_operation_run (print,
+				       GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+				       parent_window, NULL);
+
+	if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+		if (settings != NULL)
+			g_object_unref (settings);
+		settings = gtk_print_operation_get_print_settings (print);
+		g_object_ref (settings);
+	}
+
+	g_object_unref (print);
+}
+
+static void
+show_layout_response (GtkWidget * dialog, gint resp)
+{
+	GdkRectangle rect;
+	GtkWidget *kbdraw;
+	const gchar *groupName;
+
+	switch (resp) {
+	case GTK_RESPONSE_CLOSE:
+		gtk_window_get_position (GTK_WINDOW (dialog), &rect.x,
+					 &rect.y);
+		gtk_window_get_size (GTK_WINDOW (dialog), &rect.width,
+				     &rect.height);
+		matekbd_preview_save_position (&rect);
+		gtk_widget_destroy (dialog);
+		break;
+	case GTK_RESPONSE_PRINT:
+		kbdraw =
+		    GTK_WIDGET (g_object_get_data
+				(G_OBJECT (dialog), "kbdraw"));
+		groupName =
+		    (const gchar *) g_object_get_data (G_OBJECT (dialog),
+						       "groupName");
+		matekbd_keyboard_drawing_print (MATEKBD_KEYBOARD_DRAWING
+					     (kbdraw), GTK_WINDOW (dialog),
+					     groupName ? groupName :
+					     _("Unknown"));
+	}
+}
+
+GtkWidget *
+matekbd_keyboard_drawing_new_dialog (gint group, gchar * group_name)
+{
+	static MatekbdKeyboardDrawingGroupLevel groupsLevels[] = { {
+								 0, 1}, {
+									 0,
+									 3},
+	{
+	 0, 0}, {
+		 0, 2}
+	};
+	static MatekbdKeyboardDrawingGroupLevel *pGroupsLevels[] = {
+		groupsLevels, groupsLevels + 1, groupsLevels + 2,
+		groupsLevels + 3
+	};
+
+	GtkBuilder *builder;
+	GtkWidget *dialog, *kbdraw;
+	XkbComponentNamesRec component_names;
+	XklConfigRec *xkl_data;
+	GdkRectangle *rect;
+	GError *error = NULL;
+	char title[128] = "";
+	XklEngine* engine = xkl_engine_get_instance(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()));
+
+	builder = gtk_builder_new ();
+	gtk_builder_add_from_resource (builder,
+	                               "/org/mate/peripherals/keyboard/show-layout.ui",
+	                               &error);
+
+	if (error) {
+		g_error ("Could not load UI: %s", error->message);
+		g_clear_error (&error);
+	}
+
+	dialog =
+	    GTK_WIDGET (gtk_builder_get_object
+			(builder, "gswitchit_layout_view"));
+	kbdraw = matekbd_keyboard_drawing_new ();
+	gtk_widget_set_vexpand (kbdraw, TRUE);
+
+	snprintf (title, sizeof (title), _("Keyboard Layout \"%s\""),
+		  group_name);
+	gtk_window_set_title (GTK_WINDOW (dialog), title);
+	g_object_set_data_full (G_OBJECT (dialog), "group_name",
+				g_strdup (group_name), g_free);
+
+	matekbd_keyboard_drawing_set_groups_levels (MATEKBD_KEYBOARD_DRAWING
+						 (kbdraw), pGroupsLevels);
+
+	xkl_data = xkl_config_rec_new ();
+	if (xkl_config_rec_get_from_server (xkl_data, engine)) {
+		int num_layouts = g_strv_length (xkl_data->layouts);
+		int num_variants = g_strv_length (xkl_data->variants);
+		if (group >= 0 && group < num_layouts
+		    && group < num_variants) {
+			char *l = g_strdup (xkl_data->layouts[group]);
+			char *v = g_strdup (xkl_data->variants[group]);
+			char **p;
+			int i;
+
+			if ((p = xkl_data->layouts) != NULL)
+				for (i = num_layouts; --i >= 0;)
+					g_free (*p++);
+
+			if ((p = xkl_data->variants) != NULL)
+				for (i = num_variants; --i >= 0;)
+					g_free (*p++);
+
+			xkl_data->layouts =
+			    g_realloc (xkl_data->layouts,
+				       sizeof (char *) * 2);
+			xkl_data->variants =
+			    g_realloc (xkl_data->variants,
+				       sizeof (char *) * 2);
+			xkl_data->layouts[0] = l;
+			xkl_data->variants[0] = v;
+			xkl_data->layouts[1] = xkl_data->variants[1] =
+			    NULL;
+		}
+
+		if (xkl_xkb_config_native_prepare(engine, xkl_data, &component_names))
+		{
+			matekbd_keyboard_drawing_set_keyboard
+			    (MATEKBD_KEYBOARD_DRAWING (kbdraw),
+			     &component_names);
+			xkl_xkb_config_native_cleanup (engine,
+						       &component_names);
+		}
+	}
+
+	g_object_unref (G_OBJECT (xkl_data));
+
+	g_object_set_data (G_OBJECT (dialog), "builderData", builder);
+	g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (show_layout_response), NULL);
+
+	rect = matekbd_preview_load_position ();
+
+	if (rect != NULL)
+	{
+		gtk_window_move (GTK_WINDOW (dialog), rect->x, rect->y);
+		gtk_window_resize (GTK_WINDOW (dialog), rect->width, rect->height);
+		g_free (rect);
+	}
+	else
+	{
+		gtk_window_resize (GTK_WINDOW (dialog), 700, 400);
+	}
+
+	gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+
+	gtk_container_add (GTK_CONTAINER
+			   (gtk_builder_get_object
+			    (builder, "preview_vbox")), kbdraw);
+
+	g_object_set_data (G_OBJECT (dialog), "kbdraw", kbdraw);
+
+		g_signal_connect_swapped(dialog, "destroy", G_CALLBACK(g_object_unref),  g_object_get_data(G_OBJECT(dialog), "builderData"));
+
+	gtk_widget_show_all(dialog);
+
+	return dialog;
+}
+
+ +
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/4.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/4.html new file mode 100644 index 0000000..2aed6ee --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/4.html @@ -0,0 +1,1991 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+
  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
/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <config.h>
+
+#include <memory.h>
+
+#include <cairo.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gprintf.h>
+
+#include <matekbd-status.h>
+
+#include <matekbd-desktop-config.h>
+#include <matekbd-indicator-config.h>
+
+typedef struct _gki_globals {
+	XklEngine *engine;
+	XklConfigRegistry *registry;
+
+	MatekbdDesktopConfig cfg;
+	MatekbdIndicatorConfig ind_cfg;
+	MatekbdKeyboardConfig kbd_cfg;
+
+	const gchar *tooltips_format;
+	gchar **full_group_names;
+	gchar **short_group_names;
+
+	gint current_width;
+	gint current_height;
+	int real_width;
+
+	GSList *icons;		/* list of GdkPixbuf */
+	GSList *widget_instances;	/* list of MatekbdStatus */
+	gulong state_changed_handler;
+	gulong config_changed_handler;
+} gki_globals;
+
+static gchar *settings_signal_names[] = {
+	"notify::gtk-theme-name",
+	"notify::gtk-key-theme-name",
+	"notify::gtk-font-name",
+	"notify::font-options",
+};
+
+struct _MatekbdStatusPrivate {
+	gdouble angle;
+	gulong settings_signal_handlers[sizeof (settings_signal_names) /
+					sizeof (settings_signal_names[0])];
+};
+
+/* one instance for ALL widgets */
+static gki_globals globals;
+
+#define ForAllIndicators() \
+	{ \
+		GSList* cur; \
+		for (cur = globals.widget_instances; cur != NULL; cur = cur->next) { \
+			MatekbdStatus * gki = (MatekbdStatus*)cur->data;
+#define NextIndicator() \
+		} \
+	}
+
+G_DEFINE_TYPE (MatekbdStatus, matekbd_status, GTK_TYPE_STATUS_ICON)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
+static void
+matekbd_status_global_init (void);
+static void
+matekbd_status_global_term (void);
+static GdkPixbuf *
+matekbd_status_prepare_drawing (MatekbdStatus * gki, int group);
+static void
+matekbd_status_set_current_page_for_group (MatekbdStatus * gki, int group);
+static void
+matekbd_status_set_current_page (MatekbdStatus * gki);
+static void
+matekbd_status_global_cleanup (MatekbdStatus * gki);
+static void
+matekbd_status_global_fill (MatekbdStatus * gki);
+static void
+matekbd_status_set_tooltips (MatekbdStatus * gki, const char *str);
+
+void
+matekbd_status_set_tooltips (MatekbdStatus * gki, const char *str)
+{
+	g_assert (str == NULL || g_utf8_validate (str, -1, NULL));
+
+	gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (gki), str);
+}
+
+void
+matekbd_status_global_cleanup (MatekbdStatus * gki)
+{
+	while (globals.icons) {
+		if (globals.icons->data)
+			g_object_unref (G_OBJECT (globals.icons->data));
+		globals.icons =
+		    g_slist_delete_link (globals.icons, globals.icons);
+	}
+}
+
+void
+matekbd_status_global_fill (MatekbdStatus * gki)
+{
+	int grp;
+	int total_groups = xkl_engine_get_num_groups (globals.engine);
+
+	for (grp = 0; grp < total_groups; grp++) {
+		GdkPixbuf *page = matekbd_status_prepare_drawing (gki, grp);
+		globals.icons = g_slist_append (globals.icons, page);
+	}
+}
+
+static void
+matekbd_status_activate (MatekbdStatus * gki)
+{
+	xkl_debug (150, "Mouse button pressed on applet\n");
+	matekbd_desktop_config_lock_next_group (&globals.cfg);
+}
+
+/* hackish xref */
+extern gchar *matekbd_indicator_extract_layout_name (int group,
+						  XklEngine * engine,
+						  MatekbdKeyboardConfig *
+						  kbd_cfg,
+						  gchar **
+						  short_group_names,
+						  gchar **
+						  full_group_names);
+
+extern gchar *matekbd_indicator_create_label_title (int group,
+						 GHashTable **
+						 ln2cnt_map,
+						 gchar * layout_name);
+
+static void
+matekbd_status_render_cairo (cairo_t * cr, int group)
+{
+	double r, g, b;
+	PangoFontDescription *pfd;
+	PangoContext *pcc;
+	PangoLayout *pl;
+	int lwidth, lheight;
+	gchar *layout_name, *lbl_title;
+	double screen_res;
+	cairo_font_options_t *fo;
+	static GHashTable *ln2cnt_map = NULL;
+
+	xkl_debug (160, "Rendering cairo for group %d\n", group);
+	if (globals.ind_cfg.background_color != NULL &&
+	    globals.ind_cfg.background_color[0] != 0) {
+		if (sscanf
+		    (globals.ind_cfg.background_color, "%lg %lg %lg", &r,
+		     &g, &b) == 3) {
+			cairo_set_source_rgb (cr, r, g, b);
+			cairo_rectangle (cr, 0, 0, globals.current_width,
+					 globals.current_height);
+			cairo_fill (cr);
+		}
+	}
+
+	if (globals.ind_cfg.foreground_color != NULL &&
+	    globals.ind_cfg.foreground_color[0] != 0) {
+		if (sscanf
+		    (globals.ind_cfg.foreground_color, "%lg %lg %lg", &r,
+		     &g, &b) == 3) {
+			cairo_set_source_rgb (cr, r, g, b);
+		}
+	}
+
+	pcc = pango_cairo_create_context (cr);
+
+	screen_res = gdk_screen_get_resolution (gdk_screen_get_default ());
+	if (screen_res > 0)
+		pango_cairo_context_set_resolution (pcc, screen_res);
+
+	fo = cairo_font_options_copy (gdk_screen_get_font_options
+				      (gdk_screen_get_default ()));
+	/* SUBPIXEL antialiasing gives bad results on in-memory images */
+	if (cairo_font_options_get_antialias (fo) ==
+	    CAIRO_ANTIALIAS_SUBPIXEL)
+		cairo_font_options_set_antialias (fo,
+						  CAIRO_ANTIALIAS_GRAY);
+	pango_cairo_context_set_font_options (pcc, fo);
+
+	pl = pango_layout_new (pcc);
+
+	layout_name = matekbd_indicator_extract_layout_name (group,
+							  globals.engine,
+							  &globals.kbd_cfg,
+							  globals.short_group_names,
+							  globals.full_group_names);
+	lbl_title =
+	    matekbd_indicator_create_label_title (group, &ln2cnt_map,
+					       layout_name);
+
+	if (group + 1 == xkl_engine_get_num_groups (globals.engine)) {
+		g_hash_table_destroy (ln2cnt_map);
+		ln2cnt_map = NULL;
+	}
+
+	pango_layout_set_text (pl, lbl_title, -1);
+
+	g_free (lbl_title);
+
+	pfd = pango_font_description_from_string (globals.ind_cfg.font_family);
+
+	pango_layout_set_font_description (pl, pfd);
+	pango_layout_get_size (pl, &lwidth, &lheight);
+
+	cairo_move_to (cr,
+		       (globals.current_width - lwidth / PANGO_SCALE) / 2,
+		       (globals.current_height -
+			lheight / PANGO_SCALE) / 2);
+
+	pango_cairo_show_layout (cr, pl);
+
+	pango_font_description_free (pfd);
+	g_object_unref (pl);
+	g_object_unref (pcc);
+	cairo_font_options_destroy (fo);
+	cairo_destroy (cr);
+
+	globals.real_width = (lwidth / PANGO_SCALE) + 4;
+	if (globals.real_width > globals.current_width)
+		globals.real_width = globals.current_width;
+	if (globals.real_width < globals.current_height)
+		globals.real_width = globals.current_height;
+}
+
+static inline guint8
+convert_color_channel (guint8 src, guint8 alpha)
+{
+	return alpha ? ((((guint) src) << 8) - src) / alpha : 0;
+}
+
+static void
+convert_bgra_to_rgba (guint8 const *src, guint8 * dst, int width,
+		      int height, int new_width)
+{
+	int xoffset = width - new_width;
+
+	/* *4 */
+	int ptr_step = xoffset << 2;
+
+	int x, y;
+
+	/* / 2 * 4 */
+	src = src + ((xoffset >> 1) << 2);
+
+	for (y = height; --y >= 0; src += ptr_step) {
+		for (x = new_width; --x >= 0;) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+			dst[0] = convert_color_channel (src[2], src[3]);
+			dst[1] = convert_color_channel (src[1], src[3]);
+			dst[2] = convert_color_channel (src[0], src[3]);
+			dst[3] = src[3];
+#else
+			dst[0] = convert_color_channel (src[1], src[0]);
+			dst[1] = convert_color_channel (src[2], src[0]);
+			dst[2] = convert_color_channel (src[3], src[0]);
+			dst[3] = src[0];
+#endif
+			dst += 4;
+			src += 4;
+		}
+	}
+}
+
+static GdkPixbuf *
+matekbd_status_prepare_drawing (MatekbdStatus * gki, int group)
+{
+	GError *gerror = NULL;
+	char *image_filename;
+	GdkPixbuf *image;
+
+	if (globals.current_width == 0)
+		return NULL;
+
+	if (globals.ind_cfg.show_flags) {
+
+		image_filename =
+		    (char *) g_slist_nth_data (globals.
+					       ind_cfg.image_filenames,
+					       group);
+
+		image = gdk_pixbuf_new_from_file_at_size (image_filename,
+							  globals.current_width,
+							  globals.current_height,
+							  &gerror);
+
+		if (image == NULL) {
+			GtkWidget *dialog = gtk_message_dialog_new (NULL,
+								    GTK_DIALOG_DESTROY_WITH_PARENT,
+								    GTK_MESSAGE_ERROR,
+								    GTK_BUTTONS_OK,
+								    _
+								    ("There was an error loading an image: %s"),
+								    gerror
+								    ==
+								    NULL ?
+								    "Unknown"
+								    :
+								    gerror->message);
+			g_signal_connect (G_OBJECT (dialog), "response",
+					  G_CALLBACK (gtk_widget_destroy),
+					  NULL);
+
+			gtk_window_set_resizable (GTK_WINDOW (dialog),
+						  FALSE);
+
+			gtk_widget_show (dialog);
+			g_error_free (gerror);
+
+			return NULL;
+		}
+		xkl_debug (150,
+			   "Image %d[%s] loaded -> %p[%dx%d], alpha: %d\n",
+			   group, image_filename, image,
+			   gdk_pixbuf_get_width (image),
+			   gdk_pixbuf_get_height (image),
+			   gdk_pixbuf_get_has_alpha (image));
+
+		return image;
+	} else {
+		cairo_surface_t *cs =
+		    cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+						globals.current_width,
+						globals.current_height);
+		unsigned char *cairo_data;
+		guchar *pixbuf_data;
+		matekbd_status_render_cairo (cairo_create (cs), group);
+		cairo_data = cairo_image_surface_get_data (cs);
+#if 0
+		char pngfilename[20];
+		g_sprintf (pngfilename, "label%d.png", group);
+		cairo_surface_write_to_png (cs, pngfilename);
+#endif
+		pixbuf_data =
+		    g_new0 (guchar,
+			    4 * globals.real_width *
+			    globals.current_height);
+		convert_bgra_to_rgba (cairo_data, pixbuf_data,
+				      globals.current_width,
+				      globals.current_height,
+				      globals.real_width);
+
+		cairo_surface_destroy (cs);
+
+		image = gdk_pixbuf_new_from_data (pixbuf_data,
+						  GDK_COLORSPACE_RGB,
+						  TRUE,
+						  8,
+						  globals.real_width,
+						  globals.current_height,
+						  globals.real_width *
+						  4,
+						  (GdkPixbufDestroyNotify)
+						  g_free, NULL);
+		xkl_debug (150,
+			   "Image %d created -> %p[%dx%d], alpha: %d\n",
+			   group, image, gdk_pixbuf_get_width (image),
+			   gdk_pixbuf_get_height (image),
+			   gdk_pixbuf_get_has_alpha (image));
+
+		return image;
+	}
+	return NULL;
+}
+
+static void
+matekbd_status_update_tooltips (MatekbdStatus * gki)
+{
+	XklState *state = xkl_engine_get_current_state (globals.engine);
+	gchar *buf;
+	if (state == NULL || state->group < 0
+	    || state->group >= g_strv_length (globals.full_group_names))
+		return;
+
+	buf = g_strdup_printf (globals.tooltips_format,
+			       globals.full_group_names[state->group]);
+
+	matekbd_status_set_tooltips (gki, buf);
+	g_free (buf);
+}
+
+void
+matekbd_status_reinit_ui (MatekbdStatus * gki)
+{
+	matekbd_status_global_cleanup (gki);
+	matekbd_status_global_fill (gki);
+
+	matekbd_status_set_current_page (gki);
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_cfg_changed (GSettings *settings,
+			    gchar     *key,
+			    gpointer   user_data)
+{
+	xkl_debug (100,
+		   "General configuration changed in settings - reiniting...\n");
+	matekbd_desktop_config_load_from_gsettings (&globals.cfg);
+	matekbd_desktop_config_activate (&globals.cfg);
+	ForAllIndicators () {
+		matekbd_status_reinit_ui (gki);
+	} NextIndicator ();
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_ind_cfg_changed (GSettings *settings,
+				gchar     *key,
+				gpointer   user_data)
+{
+	xkl_debug (100,
+		   "Applet configuration changed in settings - reiniting...\n");
+	matekbd_indicator_config_load_from_gsettings (&globals.ind_cfg);
+
+	matekbd_indicator_config_free_image_filenames (&globals.ind_cfg);
+	matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+						    &globals.kbd_cfg);
+
+	matekbd_indicator_config_activate (&globals.ind_cfg);
+
+	ForAllIndicators () {
+		matekbd_status_reinit_ui (gki);
+	} NextIndicator ();
+}
+
+static void
+matekbd_status_load_group_names (const gchar ** layout_ids,
+			      const gchar ** variant_ids)
+{
+	if (!matekbd_desktop_config_load_group_descriptions
+	    (&globals.cfg, globals.registry, layout_ids, variant_ids,
+	     &globals.short_group_names, &globals.full_group_names)) {
+		/* We just populate no short names (remain NULL) -
+		 * full names are going to be used anyway */
+		gint i, total_groups =
+		    xkl_engine_get_num_groups (globals.engine);
+		xkl_debug (150, "group descriptions loaded: %d!\n",
+			   total_groups);
+		globals.full_group_names =
+		    g_new0 (char *, total_groups + 1);
+
+		if (xkl_engine_get_features (globals.engine) &
+		    XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+			gchar **lst = globals.kbd_cfg.layouts_variants;
+			for (i = 0; *lst; lst++, i++) {
+				globals.full_group_names[i] =
+				    g_strdup ((char *) *lst);
+			}
+		} else {
+			for (i = total_groups; --i >= 0;) {
+				globals.full_group_names[i] =
+				    g_strdup_printf ("Group %d", i);
+			}
+		}
+	}
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_kbd_cfg_callback (MatekbdStatus * gki)
+{
+	XklConfigRec *xklrec = xkl_config_rec_new ();
+	xkl_debug (100,
+		   "XKB configuration changed on X Server - reiniting...\n");
+
+	matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+						  xklrec);
+
+	matekbd_indicator_config_free_image_filenames (&globals.ind_cfg);
+	matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+						    &globals.kbd_cfg);
+
+	g_strfreev (globals.full_group_names);
+	globals.full_group_names = NULL;
+
+	if (globals.short_group_names != NULL) {
+		g_strfreev (globals.short_group_names);
+		globals.short_group_names = NULL;
+	}
+
+	matekbd_status_load_group_names ((const gchar **) xklrec->layouts,
+				      (const gchar **) xklrec->variants);
+
+	ForAllIndicators () {
+		matekbd_status_reinit_ui (gki);
+	} NextIndicator ();
+	g_object_unref (G_OBJECT (xklrec));
+}
+
+/* Should be called once for all applets */
+static void
+matekbd_status_state_callback (XklEngine * engine,
+			    XklEngineStateChange changeType,
+			    gint group, gboolean restore)
+{
+	xkl_debug (150, "group is now %d, restore: %d\n", group, restore);
+
+	if (changeType == GROUP_CHANGED) {
+		ForAllIndicators () {
+			xkl_debug (200, "do repaint\n");
+			matekbd_status_set_current_page_for_group (gki,
+								group);
+		}
+		NextIndicator ();
+	}
+}
+
+void
+matekbd_status_set_current_page (MatekbdStatus * gki)
+{
+	XklState *cur_state;
+	cur_state = xkl_engine_get_current_state (globals.engine);
+	if (cur_state->group >= 0)
+		matekbd_status_set_current_page_for_group (gki,
+							cur_state->group);
+}
+
+void
+matekbd_status_set_current_page_for_group (MatekbdStatus * gki, int group)
+{
+	xkl_debug (200, "Revalidating for group %d\n", group);
+
+	gtk_status_icon_set_from_pixbuf (GTK_STATUS_ICON (gki),
+					 GDK_PIXBUF (g_slist_nth_data
+						     (globals.icons,
+						      group)));
+
+	matekbd_status_update_tooltips (gki);
+}
+
+/* Should be called once for all widgets */
+static GdkFilterReturn
+matekbd_status_filter_x_evt (GdkXEvent * xev, GdkEvent * event)
+{
+	XEvent *xevent = (XEvent *) xev;
+
+	xkl_engine_filter_events (globals.engine, xevent);
+	switch (xevent->type) {
+	case ReparentNotify:
+		{
+			XReparentEvent *rne = (XReparentEvent *) xev;
+
+			ForAllIndicators () {
+				guint32 xid =
+				    gtk_status_icon_get_x11_window_id
+				    (GTK_STATUS_ICON (gki));
+
+				/* compare the indicator's parent window with the even window */
+				if (xid == rne->window) {
+					/* if so - make it transparent... */
+					xkl_engine_set_window_transparent
+					    (globals.engine, rne->window,
+					     TRUE);
+				}
+			}
+		NextIndicator ()}
+		break;
+	}
+	return GDK_FILTER_CONTINUE;
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_start_listen (void)
+{
+	gdk_window_add_filter (NULL, (GdkFilterFunc)
+			       matekbd_status_filter_x_evt, NULL);
+	gdk_window_add_filter (gdk_get_default_root_window (),
+			       (GdkFilterFunc) matekbd_status_filter_x_evt,
+			       NULL);
+
+	xkl_engine_start_listen (globals.engine,
+				 XKLL_TRACK_KEYBOARD_STATE);
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_stop_listen (void)
+{
+	xkl_engine_stop_listen (globals.engine, XKLL_TRACK_KEYBOARD_STATE);
+
+	gdk_window_remove_filter (NULL, (GdkFilterFunc)
+				  matekbd_status_filter_x_evt, NULL);
+	gdk_window_remove_filter
+	    (gdk_get_default_root_window (),
+	     (GdkFilterFunc) matekbd_status_filter_x_evt, NULL);
+}
+
+static void
+matekbd_status_size_changed (MatekbdStatus * gki, gint size)
+{
+	if (globals.current_height != size) {
+		globals.current_height = size;
+		globals.current_width = size * 3 / 2;
+		matekbd_status_reinit_ui (gki);
+	}
+}
+
+static void
+matekbd_status_theme_changed (GtkSettings * settings, GParamSpec * pspec,
+			   MatekbdStatus * gki)
+{
+	matekbd_indicator_config_refresh_style (&globals.ind_cfg);
+	matekbd_status_reinit_ui (gki);
+}
+
+static void
+matekbd_status_init (MatekbdStatus * gki)
+{
+	int i;
+
+	if (!g_slist_length (globals.widget_instances))
+		matekbd_status_global_init ();
+
+	gki->priv = g_new0 (MatekbdStatusPrivate, 1);
+
+	/* This should give NA a hint about the order */
+	/* commenting out fixes a Gdk-critical warning */
+/*	gtk_status_icon_set_name (GTK_STATUS_ICON (gki), "keyboard"); */
+
+	xkl_debug (100, "Initiating the widget startup process for %p\n",
+		   gki);
+
+	if (globals.engine == NULL) {
+		matekbd_status_set_tooltips (gki,
+					  _("XKB initialization error"));
+		return;
+	}
+
+	matekbd_status_set_tooltips (gki, NULL);
+
+	matekbd_status_global_fill (gki);
+	matekbd_status_set_current_page (gki);
+
+	/* append AFTER all initialization work is finished */
+	globals.widget_instances =
+	    g_slist_append (globals.widget_instances, gki);
+
+	g_signal_connect (gki, "size-changed",
+			  G_CALLBACK (matekbd_status_size_changed), NULL);
+	g_signal_connect (gki, "activate",
+			  G_CALLBACK (matekbd_status_activate), NULL);
+
+	for (i = sizeof (settings_signal_names) /
+	     sizeof (settings_signal_names[0]); --i >= 0;)
+		gki->priv->settings_signal_handlers[i] =
+		    g_signal_connect_after (gtk_settings_get_default (),
+					    settings_signal_names[i],
+					    G_CALLBACK
+					    (matekbd_status_theme_changed),
+					    gki);
+}
+
+static void
+matekbd_status_finalize (GObject * obj)
+{
+	int i;
+	MatekbdStatus *gki = MATEKBD_STATUS (obj);
+	xkl_debug (100,
+		   "Starting the mate-kbd-status widget shutdown process for %p\n",
+		   gki);
+
+	for (i = sizeof (settings_signal_names) /
+	     sizeof (settings_signal_names[0]); --i >= 0;)
+		g_signal_handler_disconnect (gtk_settings_get_default (),
+					     gki->
+					     priv->settings_signal_handlers
+					     [i]);
+
+	/* remove BEFORE all termination work is finished */
+	globals.widget_instances =
+	    g_slist_remove (globals.widget_instances, gki);
+
+	matekbd_status_global_cleanup (gki);
+
+	xkl_debug (100,
+		   "The instance of mate-kbd-status successfully finalized\n");
+
+	g_free (gki->priv);
+
+	G_OBJECT_CLASS (matekbd_status_parent_class)->finalize (obj);
+
+	if (!g_slist_length (globals.widget_instances))
+		matekbd_status_global_term ();
+}
+
+static void
+matekbd_status_global_term (void)
+{
+	xkl_debug (100, "*** Last  MatekbdStatus instance *** \n");
+	matekbd_status_stop_listen ();
+
+	matekbd_desktop_config_stop_listen (&globals.cfg);
+	matekbd_indicator_config_stop_listen (&globals.ind_cfg);
+
+	matekbd_indicator_config_term (&globals.ind_cfg);
+	matekbd_keyboard_config_term (&globals.kbd_cfg);
+	matekbd_desktop_config_term (&globals.cfg);
+
+#if GLIB_CHECK_VERSION(2,62,0)
+	if ((globals.state_changed_handler != 0) &&
+	    g_signal_handler_is_connected (globals.engine,
+	                                   globals.state_changed_handler))
+		g_clear_signal_handler (&globals.state_changed_handler,
+		                        globals.engine);
+	if ((globals.config_changed_handler != 0) &&
+	    g_signal_handler_is_connected (globals.engine,
+	                                   globals.config_changed_handler))
+		g_clear_signal_handler (&globals.config_changed_handler,
+		                        globals.engine);
+#else
+	if (g_signal_handler_is_connected
+	    (globals.engine, globals.state_changed_handler)) {
+		g_signal_handler_disconnect (globals.engine,
+					     globals.state_changed_handler);
+		globals.state_changed_handler = 0;
+	}
+	if (g_signal_handler_is_connected
+	    (globals.engine, globals.config_changed_handler)) {
+		g_signal_handler_disconnect (globals.engine,
+					     globals.config_changed_handler);
+		globals.config_changed_handler = 0;
+	}
+#endif
+
+	g_object_unref (G_OBJECT (globals.registry));
+	globals.registry = NULL;
+	g_object_unref (G_OBJECT (globals.engine));
+	globals.engine = NULL;
+	xkl_debug (100, "*** Terminated globals *** \n");
+}
+
+static void
+matekbd_status_class_init (MatekbdStatusClass * klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	xkl_debug (100, "*** First MatekbdStatus instance *** \n");
+
+	memset (&globals, 0, sizeof (globals));
+
+	/* Initing some global vars */
+	globals.tooltips_format = "%s";
+
+	/* Initing vtable */
+	object_class->finalize = matekbd_status_finalize;
+
+	/* Signals */
+}
+
+static void
+matekbd_status_global_init (void)
+{
+	XklConfigRec *xklrec = xkl_config_rec_new ();
+
+	globals.engine = xkl_engine_get_instance(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()));
+
+	if (globals.engine == NULL) {
+		xkl_debug (0, "Libxklavier initialization error");
+		return;
+	}
+
+	globals.state_changed_handler =
+	    g_signal_connect (globals.engine, "X-state-changed",
+			      G_CALLBACK (matekbd_status_state_callback),
+			      NULL);
+	globals.config_changed_handler =
+	    g_signal_connect (globals.engine, "X-config-changed",
+			      G_CALLBACK (matekbd_status_kbd_cfg_callback),
+			      NULL);
+
+	matekbd_desktop_config_init (&globals.cfg, globals.engine);
+	matekbd_keyboard_config_init (&globals.kbd_cfg, globals.engine);
+	matekbd_indicator_config_init (&globals.ind_cfg, globals.engine);
+
+	matekbd_desktop_config_start_listen (&globals.cfg,
+					  (GCallback)
+					  matekbd_status_cfg_changed, NULL);
+	matekbd_indicator_config_start_listen (&globals.ind_cfg,
+					    (GCallback)
+					    matekbd_status_ind_cfg_changed,
+					    NULL);
+
+	matekbd_desktop_config_load_from_gsettings (&globals.cfg);
+	matekbd_desktop_config_activate (&globals.cfg);
+
+	globals.registry =
+	    xkl_config_registry_get_instance (globals.engine);
+	xkl_config_registry_load (globals.registry,
+				  globals.cfg.load_extra_items);
+
+	matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+						  xklrec);
+
+	matekbd_indicator_config_load_from_gsettings (&globals.ind_cfg);
+
+	matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+						    &globals.kbd_cfg);
+
+	matekbd_indicator_config_activate (&globals.ind_cfg);
+
+	matekbd_status_load_group_names ((const gchar **) xklrec->layouts,
+				      (const gchar **) xklrec->variants);
+	g_object_unref (G_OBJECT (xklrec));
+
+	matekbd_status_start_listen ();
+
+	xkl_debug (100, "*** Inited globals *** \n");
+}
+
+GtkStatusIcon *
+matekbd_status_new (void)
+{
+	return
+	    GTK_STATUS_ICON (g_object_new (matekbd_status_get_type (), NULL));
+}
+
+/**
+ * matekbd_status_get_xkl_engine:
+ *
+ * Returns: (transfer none): The engine shared by all MatekbdStatus objects
+ */
+XklEngine *
+matekbd_status_get_xkl_engine ()
+{
+	return globals.engine;
+}
+
+/**
+ * matekbd_status_get_group_names:
+ *
+ * Returns: (transfer none) (array zero-terminated=1): List of group names
+ */
+gchar **
+matekbd_status_get_group_names ()
+{
+	return globals.full_group_names;
+}
+
+gchar *
+matekbd_status_get_image_filename (guint group)
+{
+	if (!globals.ind_cfg.show_flags)
+		return NULL;
+	return matekbd_indicator_config_get_images_file (&globals.ind_cfg,
+						      &globals.kbd_cfg,
+						      group);
+}
+
+void
+matekbd_status_set_angle (MatekbdStatus * gki, gdouble angle)
+{
+	gki->priv->angle = angle;
+}
+
+ +
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/index.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/index.html new file mode 100644 index 0000000..abc1815 --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/index.html @@ -0,0 +1,217 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmatekbd/matekbd-indicator.c
66unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
libmatekbd/matekbd-keyboard-config.c
186variableScope398styleThe scope of the variable 'p1' can be reduced.
223variableScope398styleThe scope of the variable 'group' can be reduced.
226knownConditionTrueFalse571styleCondition 'option!=NULL' is always true
279knownConditionTrueFalse570styleCondition 'variant==NULL' is always false
libmatekbd/matekbd-keyboard-drawing-resources.c
9unusedStructMember563styleunion member 'Anonymous0::alignment' is never used.
9unusedStructMember563styleunion member 'Anonymous0::ptr' is never used.
libmatekbd/matekbd-keyboard-drawing.c
1484constParameter398styleParameter 'key' can be declared as pointer to const
libmatekbd/matekbd-status.c
82unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
+
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/stats.html b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/stats.html new file mode 100644 index 0000000..1f8070c --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/stats.html @@ -0,0 +1,173 @@ + + + + + + Cppcheck - HTML report - libmatekbd + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 2
+   1  libmatekbd/matekbd-status.c
+   1  libmatekbd/matekbd-indicator.c
+

+

Top 10 files for style severity, total findings: 7
+   4  libmatekbd/matekbd-keyboard-config.c
+   2  libmatekbd/matekbd-keyboard-drawing-resources.c
+   1  libmatekbd/matekbd-keyboard-drawing.c
+

+ +
+ +
+ + diff --git a/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/style.css b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2023-07-15-131841-8798-cppcheck@5d976574dc04_v1.27.1/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