Merge branch 'master' of https://github.com/wmvanvliet/Chimara
[projects/chimara/chimara.git] / libchimara / garglk.c
1 #include <glib/gi18n.h>
2 #include <libchimara/glk.h>
3 #include "chimara-glk-private.h"
4 #include "stream.h"
5 #include "fileref.h"
6 #include "style.h"
7
8 extern GPrivate *glk_data_key;
9
10 /**
11  * garglk_fileref_get_name:
12  * @fref: A file reference.
13  *
14  * Gets the actual disk filename that @fref refers to, in the platform's
15  * native filename encoding. The string is owned by @fref and must not be
16  * changed or freed.
17  *
18  * Returns: a string in filename encoding.
19  */
20 char * 
21 garglk_fileref_get_name(frefid_t fref)
22 {
23         VALID_FILEREF(fref, return NULL);
24         return fref->filename;
25 }
26
27 /**
28  * garglk_set_program_name:
29  * @name: Name of the Glk program that is running.
30  *
31  * This function is used to let the library know the name of the currently
32  * running Glk program, in case it wants to display this information somewhere
33  * &mdash; for example, in the title bar of a window. A typical use of this
34  * function would be:
35  * |[ garglk_set_program_name("SuperGlkFrotz 0.1"); ]|
36  */
37 void 
38 garglk_set_program_name(const char *name)
39 {
40         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
41         glk_data->program_name = g_strdup(name);
42         g_object_notify(G_OBJECT(glk_data->self), "program-name");
43 }
44
45 /**
46  * garglk_set_program_info:
47  * @info: Information about the Glk program that is running.
48  *
49  * This function is used to provide the library with additional information
50  * about the currently running Glk program, in case it wants to display this
51  * information somewhere &mdash; for example, in an About box. A typical use of
52  * this function would be:
53  * |[ 
54  * garglk_set_program_info("SuperGlkFrotz, version 0.1\n"
55  *     "Original Frotz by Stefan Jokisch\n"
56  *     "Unix port by Jim Dunleavy and David Griffith\n"
57  *     "Glk port by Tor Andersson\n"
58  *     "Animation, networking, and evil AI by Sven Metcalfe");
59  * ]|
60  */
61 void 
62 garglk_set_program_info(const char *info)
63 {
64         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
65         glk_data->program_info = g_strdup(info);
66         g_object_notify(G_OBJECT(glk_data->self), "program-info");
67 }
68
69 /**
70  * garglk_set_story_name:
71  * @name: Name of the story that the Glk program is currently interpreting.
72  *
73  * If the Glk program running is an interactive fiction interpreter, then this
74  * function can be used to let the library know the name of the story currently
75  * loaded in the interpreter, in case it wants to display this information
76  * anywhere &mdash; for example, in the title bar of a window. A typical use of
77  * this function would be:
78  * |[ garglk_set_story_name("Lighan Ses Lion, el Zarf"); ]|
79  */
80 void 
81 garglk_set_story_name(const char *name)
82 {
83         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
84         glk_data->story_name = g_strdup(name);
85         g_object_notify(G_OBJECT(glk_data->self), "story-name");
86 }
87
88 /**
89  * garglk_set_line_terminators:
90  * @win: A window.
91  * @keycodes: An array of <code>keycode_</code> constants.
92  * @numkeycodes: The length of @keycodes.
93  *
94  * Amends the current line input request of @win to include terminating key
95  * codes. Any of the specified key codes will terminate the line input request 
96  * (without printing a newline). 
97  *
98  * Usually, in the event structure returned from a line input request, @val2 is
99  * zero, but if garglk_set_line_terminators() has been called during that input
100  * request, @val2 will be filled in with the key code that terminated the input
101  * request.
102  *
103  * This function only applies to one input request; any subsequent line input
104  * requests on that window are treated normally.
105  *
106  * If @numkeycodes is zero, then any previous call to 
107  * garglk_set_line_terminators() is cancelled and the input request is treated
108  * normally.
109  *
110  * <warning><para>This function is not currently implemented.</para></warning>
111  */
112 void 
113 garglk_set_line_terminators(winid_t win, const glui32 *keycodes, glui32 numkeycodes)
114 {
115         VALID_WINDOW(win, return);
116         g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
117         
118         if(win->input_request_type != INPUT_REQUEST_LINE && win->input_request_type != INPUT_REQUEST_LINE_UNICODE) {
119                 ILLEGAL(_("Tried to set the line terminators on a window without a line input request."));
120                 return;
121         }
122
123         WARNING(_("Not implemented"));
124 }
125
126 /**
127  * garglk_unput_string:
128  * @str: a null-terminated string.
129  *
130  * Removes @str from the end of the current stream, if indeed it is there. The
131  * stream's write count is decreased accordingly, and the stream's echo stream
132  * is also modified, if it has one.
133  *
134  * <warning><para>This function is not currently implemented.</para></warning>
135  */
136 void 
137 garglk_unput_string(char *str)
138 {
139         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
140         g_return_if_fail(glk_data->current_stream != NULL);
141
142         WARNING(_("Not implemented"));
143 }
144
145 /**
146  * garglk_unput_string_uni:
147  * @str: a zero-terminated array of Unicode code points.
148  *
149  * Like garglk_unput_string(), but for Unicode streams.
150  *
151  * <warning><para>This function is not currently implemented.</para></warning>
152  */
153 void 
154 garglk_unput_string_uni(glui32 *str)
155 {
156         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
157         g_return_if_fail(glk_data->current_stream != NULL);
158         
159         WARNING(_("Not implemented"));
160 }
161
162 /* TODO document */
163 void
164 garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg)
165 {
166         VALID_STREAM(str, return);
167         WARNING(_("Not implemented"));
168 }
169
170 /**
171  * garglk_set_zcolors:
172  * @fg: one of the <code>zcolor_</code> constants.
173  * @bg: one of the <code>zcolor_</code> constants.
174  *
175  * Glk works with styles, not specific colors. This is not quite compatible with
176  * the Z-machine, so this Glk extension implements Z-machine style colors.
177  *
178  * This function changes the foreground color of the current stream to @fg and 
179  * the background color to @bg.
180  *
181  * <warning><para>This function is not currently implemented.</para></warning>
182  */
183 void 
184 garglk_set_zcolors(glui32 fg, glui32 bg)
185 {
186         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
187         g_return_if_fail(glk_data->current_stream != NULL);
188         g_return_if_fail(glk_data->current_stream->window != NULL);
189
190         winid_t window = glk_data->current_stream->window;
191         GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(window->widget) );
192         //GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer);
193         GdkColor fore, back;
194         glkcolor_to_gdkcolor(fg, &fore);
195         glkcolor_to_gdkcolor(bg, &back);
196
197         gchar *id = g_strdup_printf("%d", ++window->last_zcolor_id);
198         printf("id = %s\nfg = %08X\nbg = %08X\n\n", id, fg, bg);
199         
200         GtkTextTag *tag = gtk_text_buffer_create_tag(
201                 buffer,
202                 g_strdup_printf("%d", ++window->last_zcolor_id),
203                 "foreground-gdk", &fore,
204                 "foreground-set", TRUE,
205                 "background-gdk", &back,
206                 "background-set", TRUE,
207                 NULL
208         );
209
210         window->zcolor = tag;
211 }
212
213 static void
214 apply_reverse_color(GtkTextTag *tag, gpointer data)
215 {
216         const gchar *tag_name;
217         g_object_get(tag, "name", &tag_name, NULL);
218
219         if( g_str_has_prefix(tag_name, "glk-") )
220                 g_object_set_data( G_OBJECT(tag), "reverse_color", data );
221 }
222
223 /* TODO document */
224 void
225 garglk_set_reversevideo_stream(strid_t str, glui32 reverse)
226 {
227         VALID_STREAM(str, return);
228         
229         GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(str->window->widget) );
230         GtkTextTagTable *tags = gtk_text_buffer_get_tag_table(buffer);
231         gtk_text_tag_table_foreach( tags, apply_reverse_color, GINT_TO_POINTER(reverse) );
232 }
233
234 /**
235  * garglk_set_reversevideo:
236  * @reverse: nonzero for reverse colors, zero for normal colors.
237  *
238  * If @reverse is not zero, uses the foreground color of the current stream as
239  * its background and vice versa. If @reverse is zero, changes the colors of the
240  * current stream back to normal.
241  */
242 void 
243 garglk_set_reversevideo(glui32 reverse)
244 {
245         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
246         g_return_if_fail(glk_data->current_stream != NULL);
247         g_return_if_fail(glk_data->current_stream->window != NULL);
248
249         garglk_set_reversevideo_stream(glk_data->current_stream, reverse);
250 }