1
2/*
3 ****************************************************************************** *
4 *
5 *   Copyright (C) 1999-2007, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 *
8 ****************************************************************************** *
9 */
10
11#include <gnome.h>
12#include <ft2build.h>
13#include FT_FREETYPE_H
14
15#include "pflow.h"
16
17#include "gnomeglue.h"
18
19#include "arraymem.h"
20
21struct Context
22{
23    long width;
24    long height;
25    pf_flow *paragraph;
26};
27
28typedef struct Context Context;
29
30static FT_Library engine;
31static gs_guiSupport *guiSupport;
32static fm_fontMap *fontMap;
33static le_font *font;
34
35static GSList *appList = NULL;
36
37GtkWidget *newSample(const gchar *fileName);
38void       closeSample(GtkWidget *sample);
39
40static void showabout(GtkWidget *widget, gpointer data)
41{
42    GtkWidget *aboutBox;
43    const gchar *documentedBy[] = {NULL};
44    const gchar *writtenBy[] = {
45        "Eric Mader",
46        NULL
47    };
48
49    aboutBox = gnome_about_new("Gnome Layout Sample",
50                               "0.1",
51                               "Copyright (C) 1998-2006 By International Business Machines Corporation and others. All Rights Reserved.",
52                               "A simple demo of the ICU LayoutEngine.",
53                               writtenBy,
54                               documentedBy,
55                               "",
56                               NULL);
57
58    gtk_widget_show(aboutBox);
59}
60
61#if 0
62static void notimpl(GtkObject *object, gpointer data)
63{
64    gnome_ok_dialog("Not implemented...");
65}
66#endif
67
68static gchar *prettyTitle(const gchar *path)
69{
70  const gchar *name  = g_basename(path);
71  gchar *title = g_strconcat("Gnome Layout Sample - ", name, NULL);
72
73  return title;
74}
75
76static void openOK(GtkObject *object, gpointer data)
77{
78  GtkFileSelection *fileselection = GTK_FILE_SELECTION(data);
79  GtkWidget *app = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(fileselection), "app"));
80  Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
81  gchar *fileName  = g_strdup(gtk_file_selection_get_filename(fileselection));
82  pf_flow *newPara;
83
84  gtk_widget_destroy(GTK_WIDGET(fileselection));
85
86  newPara = pf_factory(fileName, font, guiSupport);
87
88  if (newPara != NULL) {
89    gchar *title = prettyTitle(fileName);
90    GtkWidget *area = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(app), "area"));
91
92    if (context->paragraph != NULL) {
93      pf_close(context->paragraph);
94    }
95
96    context->paragraph = newPara;
97    gtk_window_set_title(GTK_WINDOW(app), title);
98
99    gtk_widget_hide(area);
100    pf_breakLines(context->paragraph, context->width, context->height);
101    gtk_widget_show_all(area);
102
103    g_free(title);
104  }
105
106  g_free(fileName);
107}
108
109static void openfile(GtkObject *object, gpointer data)
110{
111  GtkWidget *app = GTK_WIDGET(data);
112  GtkWidget *fileselection;
113  GtkWidget *okButton;
114  GtkWidget *cancelButton;
115
116  fileselection =
117    gtk_file_selection_new("Open File");
118
119  gtk_object_set_data(GTK_OBJECT(fileselection), "app", app);
120
121  okButton =
122    GTK_FILE_SELECTION(fileselection)->ok_button;
123
124  cancelButton =
125    GTK_FILE_SELECTION(fileselection)->cancel_button;
126
127  gtk_signal_connect(GTK_OBJECT(fileselection), "destroy",
128             GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
129
130  gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
131             GTK_SIGNAL_FUNC(openOK), fileselection);
132
133  gtk_signal_connect_object(GTK_OBJECT(cancelButton), "clicked",
134             GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fileselection));
135
136  gtk_window_set_modal(GTK_WINDOW(fileselection), TRUE);
137  gtk_widget_show(fileselection);
138  gtk_main();
139}
140
141static void newapp(GtkObject *object, gpointer data)
142{
143  GtkWidget *app = newSample("Sample.txt");
144
145  gtk_widget_show_all(app);
146}
147
148static void closeapp(GtkWidget *widget, gpointer data)
149{
150  GtkWidget *app = GTK_WIDGET(data);
151
152  closeSample(app);
153}
154
155static void shutdown(GtkObject *object, gpointer data)
156{
157    gtk_main_quit();
158}
159
160GnomeUIInfo fileMenu[] =
161{
162  GNOMEUIINFO_MENU_NEW_ITEM((gchar *) "_New Sample",
163                (gchar *) "Create a new Gnome Layout Sample",
164                newapp, NULL),
165
166  GNOMEUIINFO_MENU_OPEN_ITEM(openfile, NULL),
167  GNOMEUIINFO_SEPARATOR,
168  GNOMEUIINFO_MENU_CLOSE_ITEM(closeapp, NULL),
169  GNOMEUIINFO_MENU_EXIT_ITEM(shutdown, NULL),
170  GNOMEUIINFO_END
171};
172
173GnomeUIInfo helpMenu[] =
174{
175    /* GNOMEUIINFO_HELP("gnomelayout"), */
176    GNOMEUIINFO_MENU_ABOUT_ITEM(showabout, NULL),
177    GNOMEUIINFO_END
178};
179
180GnomeUIInfo mainMenu[] =
181{
182    GNOMEUIINFO_SUBTREE(N_((gchar *) "File"), fileMenu),
183    GNOMEUIINFO_SUBTREE(N_((gchar *) "Help"), helpMenu),
184    GNOMEUIINFO_END
185};
186
187static gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
188{
189  closeSample(widget);
190
191  /* indicate that closeapp  already destroyed the window */
192  return TRUE;
193}
194
195static gint eventConfigure(GtkWidget *widget, GdkEventConfigure *event, Context *context)
196{
197  if (context->paragraph != NULL) {
198    context->width  = event->width;
199    context->height = event->height;
200
201    if (context->width > 0 && context->height > 0) {
202        pf_breakLines(context->paragraph, context->width, context->height);
203    }
204  }
205
206  return TRUE;
207}
208
209static gint eventExpose(GtkWidget *widget, GdkEvent *event, Context *context)
210{
211  if (context->paragraph != NULL) {
212    gint maxLines = pf_getLineCount(context->paragraph) - 1;
213    gint firstLine = 0, lastLine = context->height / pf_getLineHeight(context->paragraph);
214    rs_surface *surface = rs_gnomeRenderingSurfaceOpen(widget);
215
216    pf_draw(context->paragraph, surface, firstLine, (maxLines < lastLine)? maxLines : lastLine);
217
218    rs_gnomeRenderingSurfaceClose(surface);
219  }
220
221  return TRUE;
222}
223
224GtkWidget *newSample(const gchar *fileName)
225{
226  Context *context = NEW_ARRAY(Context, 1);
227  gchar *title;
228  GtkWidget *app;
229  GtkWidget *area;
230  GtkStyle *style;
231  int i;
232
233  context->width  = 600;
234  context->height = 400;
235  context->paragraph = pf_factory(fileName, font, guiSupport);
236
237  title = prettyTitle(fileName);
238  app = gnome_app_new("gnomeLayout", title);
239
240  gtk_object_set_data(GTK_OBJECT(app), "context", context);
241
242  gtk_window_set_default_size(GTK_WINDOW(app), 600 - 24, 400);
243
244  gnome_app_create_menus_with_data(GNOME_APP(app), mainMenu, app);
245
246  gtk_signal_connect(GTK_OBJECT(app), "delete_event",
247             GTK_SIGNAL_FUNC(eventDelete), NULL);
248
249  area = gtk_drawing_area_new();
250  gtk_object_set_data(GTK_OBJECT(app), "area", area);
251
252  style = gtk_style_copy(gtk_widget_get_style(area));
253
254  for (i = 0; i < 5; i += 1) {
255    style->fg[i] = style->white;
256  }
257
258  gtk_widget_set_style(area, style);
259
260  gnome_app_set_contents(GNOME_APP(app), area);
261
262  gtk_signal_connect(GTK_OBJECT(area),
263             "expose_event",
264             GTK_SIGNAL_FUNC(eventExpose),
265             context);
266
267  gtk_signal_connect(GTK_OBJECT(area),
268             "configure_event",
269             GTK_SIGNAL_FUNC(eventConfigure),
270             context);
271
272  appList = g_slist_prepend(appList, app);
273
274  g_free(title);
275
276  return app;
277}
278
279void closeSample(GtkWidget *app)
280{
281  Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
282
283  if (context->paragraph != NULL) {
284    pf_close(context->paragraph);
285  }
286
287  DELETE_ARRAY(context);
288
289  appList = g_slist_remove(appList, app);
290
291  gtk_widget_destroy(app);
292
293  if (appList == NULL) {
294    gtk_main_quit();
295  }
296}
297
298int main (int argc, char *argv[])
299{
300    LEErrorCode   fontStatus = LE_NO_ERROR;
301    poptContext   ptctx;
302    GtkWidget    *app;
303    const char   *defaultArgs[] = {"Sample.txt", NULL};
304    const char  **args;
305    int i;
306
307    FT_Init_FreeType(&engine);
308
309    gnome_init_with_popt_table("gnomelayout", "0.1", argc, argv, NULL, 0, &ptctx);
310
311    guiSupport = gs_gnomeGuiSupportOpen();
312    fontMap    = fm_gnomeFontMapOpen(engine, "FontMap.Gnome", 24, guiSupport, &fontStatus);
313    font       = le_scriptCompositeFontOpen(fontMap);
314
315    if (LE_FAILURE(fontStatus)) {
316        FT_Done_FreeType(engine);
317        return 1;
318    }
319
320    args = poptGetArgs(ptctx);
321
322    if (args == NULL) {
323        args = defaultArgs;
324    }
325
326    for (i = 0; args[i] != NULL; i += 1) {
327       app = newSample(args[i]);
328
329       gtk_widget_show_all(app);
330    }
331
332    poptFreeContext(ptctx);
333
334    gtk_main();
335
336    le_fontClose(font);
337    gs_gnomeGuiSupportClose(guiSupport);
338
339    FT_Done_FreeType(engine);
340
341    exit(0);
342}
343