How to apply style using GtkSourceView library - gtk3

I'm trying to style a GtkSourceView object in particular I'd like to change the color of line numbers. I'm reading Style Scheme Definition Reference: GtkSourceView 4 Reference Manual. I'm able to change text but not line-numbers. The document says:
line-numbers : Text and background colors for the left margin, on which line numbers are drawn.
This is the source:
#include <gtk/gtk.h>
#include <gtksourceview/gtksource.h>
int main (int argc,
char *argv[])
{
GtkWidget *window, *scrolled_win, *textview;
GtkWidget *vbox, *menubar, *fileMenu, *fileMi, *quit_item;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_maximize(GTK_WINDOW (window));
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_window_set_title (GTK_WINDOW (window), "Text Views");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
textview = gtk_source_view_new();
menubar = gtk_menu_bar_new();
fileMenu = gtk_menu_new();
fileMi = gtk_menu_item_new_with_label("File");
quit_item = gtk_menu_item_new_with_label("Quit");
gtk_widget_set_hexpand(textview, TRUE);
gtk_widget_set_vexpand(textview, TRUE);
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_path (provider,
"gtk-widgets.css", NULL);
GtkStyleContext *context;
context = gtk_widget_get_style_context(textview);
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quit_item);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add(GTK_CONTAINER(vbox), scrolled_win);
gtk_container_add (GTK_CONTAINER (scrolled_win), textview);
gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW(textview), TRUE);
gtk_widget_show_all (window);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(quit_item), "activate",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
This is the CSS file:
text {
background-color: #002b36;
color: #c7a21d;
}
line-numbers {
background-color: red;
color:red;
}
current-line-number {
background-color: red;
color:red;
}
selection{
color:yellow;
}
What am I doing wrong?

The API has a way to access the default styles like this:
manager = GtkSource.StyleSchemeManager().get_default()
print (manager.get_scheme_ids())
>['classic', 'cobalt', 'kate', 'oblivion', 'solarized-dark', 'solarized-light', 'tango']
scheme = manager.get_scheme("oblivion")
buffer.set_style_scheme(scheme)
An example for good measure:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
from gi.repository import GtkSource as gtksource
from gi.repository import Pango
view = gtksource.View()
view.modify_font(Pango.FontDescription('monospace 11'))
view.set_show_line_numbers(True)
view.set_show_line_marks(True)
buffer = view.get_buffer()
filename = "treeview.py"
txt = open(filename).read()
buffer.set_text(txt)
# set language, syntax highlighting
lm = gtksource.LanguageManager.new()
lang = lm.guess_language(filename)
buffer.set_highlight_syntax(True)
buffer.set_language(lang)
buffer.create_tag("invisible",invisible=True)
manager = gtksource.StyleSchemeManager().get_default()
scheme = manager.get_scheme("monokai")
buffer.set_style_scheme(scheme)
window = gtk.Window()
window.connect("destroy", gtk.main_quit)
window.add(view)
window.show_all()
gtk.main()
From there you should be able use the guide to apply custom themes, change colours of certain elements, etc...

Related

Voila not clearing output/dispalying new output

I am trying to get an ipywidget button to change colour when clicked. I figured a way to do it as below
import ipywidgets as ipw
from ipywidgets import *
from IPython.display import display, HTML, clear_output
from IPython.display import display, HTML
pdf_btn = ipw.Button(description = 'Run PDF',button_style = 'danger',
layout=Layout(width='150px', height='30px'))
new_btn = ipw.Button(description = 'PDF done',button_style = 'success',
layout=Layout(width='150px', height='30px'))
HBox = ipw.HBox([pdf_btn])
HBox1 = ipw.HBox([new_btn])
def clear(b):
clear_output()
display(HBox1)
pdf_btn.on_click(clear)
display(HBox)
When inputting this code in Jupyter Notebook and rendering through Voila nothing happens.
Any ideas why ? And any suggestions ?
You can just update the button style maybe? Like so:
import ipywidgets as ipw
from ipywidgets import *
from IPython.display import display, HTML, clear_output
from IPython.display import display, HTML
pdf_btn = ipw.Button(description = 'Run PDF',button_style = 'danger',
layout=Layout(width='150px', height='30px'))
HBox = ipw.HBox([pdf_btn])
def clear(b):
pdf_btn.button_style="success"
pdf_btn.description="PDF done"
pdf_btn.on_click(clear)
display(HBox)
Note that your code fails in JupyterLab.
Voila is much more similar to JupyterLab's rendering machinery than the classic interface. For now, it is best to use JupyterLab in conjunction with developing for Voila. (Note that this will change soon as the underlying machinery for what is now the traditional Jupyter notebook interface will soon run on machinery more in line with JupyterLab, see Build Jupyter Notebook v7 off of JupyterLab components. A lot of the old code / approaches will then consistently not work and either interface will be as suitable for developing with Voila in mind.)
When your code fails in JupyterLab it logs that to the console, similar to as shown here. I suspect you could follow Jason's advice, what I reference in my reply, which is here, if you actually want the other button there. (I guess I should say if you actually want the other HBox there since for some reason you have each button in a separate HBox in your code.) In other words, you'd need to add in how to handle the output from HBox1 correctly as part of the main output. Yours is going to the JupyterLab Log console as it is now.
So one option is to add HBox1 in as a displayed item, yet hide it initially:
import ipywidgets as ipw
from ipywidgets import *
from IPython.display import display, HTML, clear_output
from IPython.display import display, HTML
pdf_btn = ipw.Button(description = 'Run PDF',button_style = 'danger',
layout=Layout(width='150px', height='30px'))
new_btn = ipw.Button(description = 'PDF done',button_style = 'success',
layout=Layout(width='150px', height='30px'))
HBox = ipw.HBox([pdf_btn])
HBox1 = ipw.HBox([new_btn])
HBox1.layout.visibility = 'hidden' #based on https://github.com/jupyter-widgets/ipywidgets/issues/674#issuecomment-234321603
def clear(b):
HBox1.layout.visibility = 'visible'
HBox.layout.display = 'none' #based on https://stackoverflow.com/a/54134344/8508004
pdf_btn.on_click(clear)
display(HBox)
display(HBox1)
You could also make an overarching vertical box for the items and then toggle which one it contains, similar to here. This is the 'cleanest' option I'll list here, other than just having one button & changing the button itself:
import ipywidgets as ipw
from ipywidgets import *
from IPython.display import display, HTML, clear_output
from IPython.display import display, HTML
pdf_btn = ipw.Button(description = 'Run PDF',button_style = 'danger',
layout=Layout(width='150px', height='30px'))
new_btn = ipw.Button(description = 'PDF done',button_style = 'success',
layout=Layout(width='150px', height='30px'))
HBox = ipw.HBox([pdf_btn])
HBox1 = ipw.HBox([new_btn])
vb = VBox(children = [HBox])
def clear(b):
vb.children = [HBox1]
pdf_btn.on_click(clear)
display(vb)
('cleanest' in regards to it not creating extra space in the output area.)
Or combine the vertical box approach with the approach of toggling off via the layout settings:
import ipywidgets as ipw
from ipywidgets import *
from IPython.display import display, HTML, clear_output
from IPython.display import display, HTML
pdf_btn = ipw.Button(description = 'Run PDF',button_style = 'danger',
layout=Layout(width='150px', height='30px'))
new_btn = ipw.Button(description = 'PDF done',button_style = 'success',
layout=Layout(width='150px', height='30px'))
HBox = ipw.HBox([pdf_btn])
HBox1 = ipw.HBox([new_btn])
HBox1.layout.visibility = 'hidden' #based on https://github.com/jupyter-widgets/ipywidgets/issues/674#issuecomment-234321603
vb = VBox(children = [HBox, HBox1])
def clear(b):
HBox1.layout.visibility = 'visible'
HBox.layout.display = 'none' #based on https://stackoverflow.com/a/54134344/8508004
pdf_btn.on_click(clear)
display(vb)
And if you want to fully leverage Jupyter's display system further, combine it with an overarching out so you can use print(), too:
import ipywidgets as ipw
from ipywidgets import *
from IPython.display import display, HTML, clear_output
from IPython.display import display, HTML
out = widgets.Output()
pdf_btn = ipw.Button(description = 'Run PDF',button_style = 'danger',
layout=Layout(width='150px', height='30px'))
new_btn = ipw.Button(description = 'PDF done',button_style = 'success',
layout=Layout(width='150px', height='30px'))
HBox = ipw.HBox([pdf_btn])
HBox1 = ipw.HBox([new_btn])
vb = VBox(children = [HBox])
def clear(b):
vb.children = [HBox1]
with out:
print('Enjoy!')
pdf_btn.on_click(clear)
with out:
display(vb)
out

How to use and compile standard c Lib in vala?

I'm just start few test in vala.
Vala is new for me . Sure I started to read a lot of tuto, but I don't understand my mistake.
how to use and compile the follow code?
using Gtk;
#include <stdio.h>
// compile with valac --pkg gtk+-3.0 hello_world_gtk_01.vala
public const int EXIT_SUCCESS=0;
int main (string[] args)
{
Gtk.init (ref args);
var window = new Window ();
window.title = "Hello, World!";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
stdout.printf ("Version de gtk: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION);
stdout.printf ("Version de gtk: %u.%u.%u\n", get_major_version() , get_minor_version(), get_micro_version());
string name, str;
name = "Version de gtk: ";
sprintf(str, "%d", get_major_version());
name = name+ str;
sprintf(str, "%d", get_minor_version());
name = name+ str;
sprintf(str, "%d", get_micro_version());
name = name+ str+ "\n";
var label = new Label (name);
window.add (label);
window.show_all ();
Gtk.main ();
return EXIT_SUCCESS;
}
What is bad ?
Gcc said
hello_world_gtk_01.vala:2.2-2.9: error: syntax error, invalid preprocessing directive
#include <stdio.h>
^^^^^^^^
hello_world_gtk_01.vala:2.10-2.10: error: syntax error, expected identifier
#include <stdio.h>
^
Compilation failed: 2 error(s), 0 warning(s)
could you help me to understand how to manage stdio?
Vala generates C code, but you can't pass C straight from the Vala file to the generated C. The Vala [CCode] attribute gives fine control over the generated C, but you won't need that in most cases. For an example of standard C names and their GLib equivalents take a look at the glib-2.0.vapi file in the Vala repository. Other standard C and POSIX extensions are in posix.vapi. There is also an in depth tutorial on writing a binding from Vala to a C library. Writing a binding, however, is a more advanced topic and what you are trying to achieve in your example doesn't need a new binding.
Your example uses string interpolation. In Vala a data type can have a method, so one way to write what you want would be:
name = "Version de gtk: %u.%u.%u\n".printf( get_major_version (), get_minor_version (), get_micro_version ());
Vala also has a string template syntax, #"", and and then an expression, $(), inside the string is evaluated. For example:
name = #"Version de gtk: $(get_major_version ()).$(get_minor_version ()).$(get_micro_version ())\n";
This works because uint, the return value of the function calls, has a to_string () method that is implicitly called by the string template.
Here's your example modified to use the string template method:
using Gtk;
// compile with valac --pkg gtk+-3.0 hello_world_gtk_01.vala
public const int EXIT_SUCCESS=0;
int main (string[] args)
{
Gtk.init (ref args);
var window = new Window ();
window.title = "Hello, World!";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
stdout.printf ("Version de gtk: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION);
stdout.printf ("Version de gtk: %u.%u.%u\n", get_major_version() , get_minor_version(), get_micro_version());
var name = #"Version de gtk: $(get_major_version ()).$(get_minor_version ()).$(get_micro_version ())\n";
var label = new Label (name);
window.add (label);
window.show_all ();
Gtk.main ();
return EXIT_SUCCESS;
}

How to insert dialog in submenu with GTK+ C++?

I'm new in GTK+ (c++).I use this version of gtk: gtk+ bundle_3.4.2-20130513_win64 and I designed a menu (Help) with two sup menus: OpenCV and GTK.
I want to insert dialog for any of them in sub menu with GTK+ C++. Similar to this:
In fact my final result is:
But I can not. What ideas on how to solve this task would you suggest? Or on what resource on the internet can I find help?
this is my c++ code:
GtkWidget *vbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, FALSE);
gtk_container_set_border_width(GTK_CONTAINER(win), 10);
gtk_table_attach_defaults(GTK_TABLE(table), vbox2, 1, 2, 0, 1);
GtkWidget *menubar2 = gtk_menu_bar_new();
GtkWidget *helpMenu = gtk_menu_new();
GtkAccelGroup *accel_group2 = NULL;
accel_group2 = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(win), accel_group2);
GtkWidget *helpMi = gtk_menu_item_new_with_mnemonic("_Help");
//opencvMi
GtkWidget *imageOpenCV, *opencvMi;
imageOpenCV = gtk_image_new_from_file("E:/Works for Gov Project/DOC /GUI/logogui1/opencv.png");
opencvMi = gtk_image_menu_item_new_with_mnemonic("OpenCV");
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(opencvMi), GTK_WIDGET(imageOpenCV));
gtk_widget_show(opencvMi);
GtkWidget *linkbutton_opencv = gtk_menu_item_new_with_label("http://www.opencv.org");
//gtkMi
GtkWidget *imageGTK,*gtkMi;
imageGTK = gtk_image_new_from_file("E:/Works for Gov Project/DOC /GUI/logogui1/gtk.png");
gtkMi = gtk_image_menu_item_new_with_mnemonic("GTK+");
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gtkMi), GTK_WIDGET(imageGTK));
gtk_widget_show(gtkMi);
GtkWidget *linkbutton_gtk = gtk_menu_item_new_with_label("http://www.gtk.org/");
GtkWidget *imprMenu2 = gtk_menu_new();
GtkWidget *imprMenu3 = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(helpMi), helpMenu);
gtk_menu_shell_append(GTK_MENU_SHELL(helpMenu), opencvMi);
gtk_menu_shell_append(GTK_MENU_SHELL(helpMenu), gtkMi);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar2), helpMi);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(opencvMi), imprMenu2);
gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu2), linkbutton_opencv);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtkMi), imprMenu3);
gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu3), linkbutton_gtk);
gtk_box_pack_start(GTK_BOX(vbox2), menubar2, FALSE, FALSE, 0);
and this is code for dialog (GtkAboutDialog):
http://zetcode.com/gui/gtk2/gtkdialogs/

GetPrivateProfileString failed when I use gflags to enable page heap with flags(full unaligned traces)

My code is like this:
#include <Windows.h>
#include <tchar.h>
int main () {
TCHAR conffigPath[MAX_PATH] = {0};
GetCurrentDirectory(MAX_PATH, conffigPath);
_tcscat_s(conffigPath, MAX_PATH, _T("\\config.ini"));
TCHAR szValue[MAX_PATH] = {0};
GetPrivateProfileString(_T("361"), _T("DLL"), NULL, szValue, MAX_PATH, conffigPath);
return 0;
}
The context of config.ini is following:
[361]
Dll=daemon.dll
But when GetPrivateProfileString was called, the context of szValue is empty! And when I disable the pageheap, the context of szValue is "daemon.dll".
And when I enable pageheap with flags(full traces),the context of szVaule is "daemon.dll".
Is there a bug of the API GetPrivateProfileString?

process flex+bison output in gtk hash table and list store

this question follows the discussion of flex+bison output in a glib's hash container
Let me repost it (last post remained unanswered after some discussions.)
I want to parse a bibtex file using flex and bison, and will display those data using gtk library(in C).
The lexer is
%{
#include "bib.tab.h"
%}
%%
[A-Za-z][A-Za-z0-9]* { yylval.sval = strdup(yytext); return KEY; }
\"([^\"]|\\.)*\"|\{([^\"]|\\.)*\} { yylval.sval = strdup(yytext); return VALUE; }
[ \t\n] ; /* ignore whitespace */
[{}#=,] { return *yytext; }
. { fprintf(stderr, "Unrecognized character %c in input\n", *yytext); }
%%
and the parser is:
%{
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <string.h>
#include <glib/gstdio.h>
#include <fcntl.h>
enum
{
COL_BIB_KEY=0,
COL_BIB_TYPE, COL_BIB_AUTHOR, COL_BIB_YEAR,
NUM_COLS} ;
#define slen 1024
GHashTable* table;
GtkTreeIter siter;
GtkListStore *store;
%}
// Symbols.
%union
{
char *sval;
};
%token <sval> VALUE
%token <sval> KEY
%token OBRACE
%token EBRACE
%token QUOTE
%token SEMICOLON
%start Input
%%
Input:
/* empty */
| Input Entry ; /* input is zero or more entires */
Entry:
'#' KEY '{' KEY ','{ g_hash_table_insert(table, g_strdup("TYPE"), g_strdup($2));
g_hash_table_insert(table, g_strdup("ID"), g_strdup($4));
g_printf("%s:%s\n","KEY=>",g_hash_table_lookup(table,"TYPE"));
// g_printf("%s: %s\n", $2, $4);
}
KeyVals '}'
;
KeyVals:
/* empty */
| KeyVals KeyVal ; /* zero or more keyvals */
KeyVal:
KEY '=' VALUE ',' { g_hash_table_insert(table, g_strdup($1), g_strdup($3));
// g_printf("%s: %s\n", $1, $3);
};
%%
int yyerror(char *s) {
printf("yyerror : %s\n",s);
}
int main(int argc, char** argv) {
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *tree=gtk_tree_view_new();
setup_tree(tree);
gtk_container_add (GTK_CONTAINER (window), tree);
store= gtk_list_store_new (NUM_COLS,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
table = g_hash_table_new(g_str_hash, g_str_equal);
gint i;
do{
g_hash_table_remove_all (table);
yyparse();
parse_entry (table);
gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (store));
g_object_unref (store);
}
while(!EOF);
g_hash_table_destroy (table);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void parse_entry (GHashTable *table)
{
GHashTableIter iter;
gchar *key, *val;
char *keys[] = {"id", "type", "author", "year", "title", "publisher", "editor",
"volume", "number", "pages", "month", "note", "address", "edition", "journal",
"series", "book", "chapter", "organization", NULL};
char *vals[] = {NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL};
gchar **kiter;
gint i;
g_hash_table_iter_init (&iter, table);
while (g_hash_table_iter_next (&iter, (void **)&key, (void **)&val))
{
for (kiter = keys, i = 0; *kiter; kiter++, i++)
{
if (!g_ascii_strcasecmp(*kiter, key))
{
vals[i] = g_strndup(val,slen);
// g_printf("%s:%s\n",keys[i],g_hash_table_lookup(table,keys[i]));
g_printf("%d=>%s:%s\n",i,keys[i],vals[i]);
break;
}
}
}
gtk_list_store_append (store, &siter);
gtk_list_store_set (store, &siter,
COL_BIB_TYPE, vals[COL_BIB_TYPE],
COL_BIB_KEY, vals[COL_BIB_KEY],
COL_BIB_AUTHOR, vals[COL_BIB_AUTHOR],
COL_BIB_YEAR, vals[COL_BIB_YEAR],
-1);
}
void setup_tree(GtkWidget *tree){
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes
("Type", renderer, "text",COL_BIB_TYPE , NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes
("Author", renderer, "text", COL_BIB_AUTHOR, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes
("Year", renderer, "text",COL_BIB_YEAR, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
g_printf("HIIIIIIIIIi");
}
The problem is on populating the hash table, and not the listview(I enclosed the list store so that people can see my final goal and suggest improvements.)
If we put the line
g_printf("%s:%s\n",$1,g_hash_table_lookup(table,$1));
at line number 50, it prints the hash table's content correctly, but if we want the content by uncommenting line number 105, then only the last entry is parsed.
So, my guess is I am not processing the hash file correctly (line no 97-107 may be?)
The makefile is:
CC=gcc -g
FLEX=flex
BISON=bison
LIBS=lfl
PROG=parse
${PROG}:bib.y bib.l
${BISON} -d bib.y
${FLEX} -i bib.l
${CC} lex.yy.c bib.tab.c `pkg-config --cflags --libs glib-2.0``pkg-config --cflags --libs gtk+-3.0` -${LIBS} -o $#
clean:
rm -f lex.yy.c bib.tab.c ${PROG}
touch bib.l bib.y
and a sample bibtex file is:
#Book{a1,
Title="ASR",
Publisher="oxf",
author = "a {\"m}ook, Rudra Banerjee",
Year="2010",
Address="UK",
Edition="1",
}
#Booklet{ab19,
Author="Rudra Banerjee and A. Mookerjee",
Title="Fe{\"Ni}Mo",
Editor="sm1",
Title="sm2",
Publisher="sm3",
Volume="sm4",
Number="sm5",
Pages="sm6",
Month="sm8",
Note="sm9",
Key="sm10",
Year="1980",
Address="osm1",
Edition="osm2",
}
I will be grateful if someone shows me some way to populate the hashtable correctly.
Please help.
It looks like you're just dumping all the data into a single hash table. So the first entry will go into the hash table unders the keys TYPE, ID, Title, Publisher, etc. Then the second entry will overwrite those same keys and values (except it uses Author instead of author), leading to a mix of the two entries.
If you want to use a hashtable, I would expect you'd need a hash table for each entry, and a hastable of hashtables to map IDs to hashtables containing the info for that entry. Alternately, you could parse each entry into a list or some other container structure, and have a single hashtable mapping IDs to lists/containers.
You're also leaking memory very rapidly, as you allocate new memory for each KEY or VALUE and then duplicate the memory to put it into the hashtable.