~ubuntu-branches/ubuntu/hardy/uim/hardy

« back to all changes in this revision

Viewing changes to helper/helper-candwin-gtk.c

  • Committer: Bazaar Package Importer
  • Author(s): Steinar H. Gunderson
  • Date: 2006-07-06 22:17:24 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060706221724-6sobw1fcsxj647hp
Tags: 1:1.1.0-1.2
* Non-maintainer upload.
* Added -Wno-cast-align to CFLAGS, as per the RM's recommendations:

  < vorlon> Sesse: -Wno-cast-align and to hell with it :P

  Really fixes FTBFS. (Really Closes: #375081)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
  Copyright (c) 2003-2005 uim Project http://uim.freedesktop.org/
4
 
 
5
 
  All rights reserved.
6
 
 
7
 
  Redistribution and use in source and binary forms, with or without
8
 
  modification, are permitted provided that the following conditions
9
 
  are met:
10
 
 
11
 
  1. Redistributions of source code must retain the above copyright
12
 
     notice, this list of conditions and the following disclaimer.
13
 
  2. Redistributions in binary form must reproduce the above copyright
14
 
     notice, this list of conditions and the following disclaimer in the
15
 
     documentation and/or other materials provided with the distribution.
16
 
  3. Neither the name of authors nor the names of its contributors
17
 
     may be used to endorse or promote products derived from this software
18
 
     without specific prior written permission.
19
 
 
20
 
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21
 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 
  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24
 
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 
  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 
  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 
  SUCH DAMAGE.
31
 
 
32
 
*/
33
 
 
34
 
#ifdef HAVE_CONFIG_H
35
 
#  include <config.h>
36
 
#endif
37
 
#include <uim/uim.h>
38
 
#include <uim/uim-helper.h>
39
 
#include <gtk/gtk.h>
40
 
#include <gdk/gdkx.h>
41
 
#include <glib/gprintf.h>
42
 
#include <stdlib.h>
43
 
#include <string.h>
44
 
#include <sys/types.h>
45
 
#include <unistd.h>
46
 
 
47
 
#include "../gtk/caret-state-indicator.h"
48
 
 
49
 
#define UIM_TYPE_CANDIDATE_WINDOW       (candidate_window_get_type())
50
 
#define UIM_CANDIDATE_WINDOW(obj)       (G_TYPE_CHECK_INSTANCE_CAST ((obj), candidate_window_get_type(), UIMCandidateWindow))
51
 
#define UIM_IS_CANDIDATE_WINDOW(obj)    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UIM_TYPE_CANDIDATE_WINDOW))
52
 
#define UIM_IS_CANDIDATE_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), UIM_TYPE_CANDIDATE_WINDOW))
53
 
#define UIM_CANDIDATE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UIM_TYPE_CANDIDATE_WINDOW, UIMCandidateWindowClass))
54
 
 
55
 
typedef struct _UIMCandidateWindow      UIMCandidateWindow;
56
 
typedef struct _UIMCandidateWindowClass UIMCandidateWindowClass;
57
 
 
58
 
struct _UIMCandidateWindow {
59
 
  GtkWindow parent;
60
 
 
61
 
  GtkWidget *view;
62
 
  GtkWidget *num_label;
63
 
 
64
 
  GPtrArray *stores;
65
 
 
66
 
  guint nr_candidates;
67
 
  guint display_limit;
68
 
  gint candidate_index;
69
 
  gint page_index;
70
 
 
71
 
  gint pos_x;
72
 
  gint pos_y;
73
 
  gint width;
74
 
  gint height;
75
 
 
76
 
  GtkWidget *caret_state_indicator;
77
 
 
78
 
  gboolean is_active;
79
 
};
80
 
 
81
 
struct _UIMCandidateWindowClass {
82
 
  GtkWindowClass parent_class;
83
 
 
84
 
  /* signals */
85
 
  void (*index_changed) (UIMCandidateWindowClass *candwin);
86
 
};
87
 
 
88
 
static UIMCandidateWindow *cwin; /* use static one */
89
 
 
90
 
GType candidate_window_get_type(void);
91
 
UIMCandidateWindow *candidate_window_new(void);
92
 
 
93
 
/* copied from uim-cand-win-gtk.c */
94
 
static gint uim_cand_win_gtk_get_index(UIMCandidateWindow *cwin);
95
 
static void uim_cand_win_gtk_set_index(UIMCandidateWindow *cwin, gint index);
96
 
static void uim_cand_win_gtk_set_page(UIMCandidateWindow *cwin, gint page);
97
 
 
98
 
static void uim_cand_win_gtk_layout(void);
99
 
 
100
 
#define NR_CANDIDATES 10 /* FIXME! not used */
101
 
#define CANDWIN_DEFAULT_WIDTH   80
102
 
 
103
 
enum {
104
 
  INDEX_CHANGED_SIGNAL,
105
 
  NR_SIGNALS
106
 
};
107
 
 
108
 
enum {
109
 
  TERMINATOR = -1,
110
 
  COLUMN_HEADING,
111
 
  COLUMN_CANDIDATE
112
 
};
113
 
 
114
 
static void candidate_window_init(UIMCandidateWindow *cwin);
115
 
static void candidate_window_class_init(UIMCandidateWindowClass *klass);
116
 
 
117
 
static gboolean tree_selection_changed(GtkTreeSelection *selection,
118
 
                                       GtkTreeModel *model,
119
 
                                       GtkTreePath *path,
120
 
                                       gboolean path_currently_selected,
121
 
                                       gpointer data);
122
 
 
123
 
#if 0
124
 
static gboolean tree_view_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data);
125
 
#endif
126
 
static gboolean configure_event_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
127
 
 
128
 
static GType candidate_window_type = 0;
129
 
static GTypeInfo const object_info = {
130
 
  sizeof (UIMCandidateWindowClass),
131
 
  NULL,
132
 
  NULL,
133
 
  (GClassInitFunc) candidate_window_class_init,
134
 
  NULL,
135
 
  NULL,
136
 
  sizeof(UIMCandidateWindow),
137
 
  0,
138
 
  (GInstanceInitFunc) candidate_window_init,
139
 
};
140
 
 
141
 
static gint cand_win_gtk_signals[NR_SIGNALS] = {0};
142
 
 
143
 
static unsigned int read_tag;
144
 
 
145
 
static void init_candidate_win(void);
146
 
static void candwin_activate(gchar **str);
147
 
static void candwin_update(gchar **str);
148
 
static void candwin_move(char **str);
149
 
static void candwin_show(void);
150
 
static void candwin_deactivate(void);
151
 
static void str_parse(char *str);
152
 
 
153
 
static void index_changed_cb(UIMCandidateWindow *cwin)
154
 
{
155
 
  fprintf(stdout, "index\n");
156
 
  fprintf(stdout, "%d\n\n", uim_cand_win_gtk_get_index(cwin));
157
 
  fflush(stdout);
158
 
}
159
 
 
160
 
GType
161
 
candidate_window_get_type(void)
162
 
{
163
 
  if (!candidate_window_type)
164
 
    candidate_window_type = g_type_register_static(GTK_TYPE_WINDOW,
165
 
                    "UIMCandidateWindow", &object_info, (GTypeFlags)0);
166
 
  return candidate_window_type;
167
 
}
168
 
 
169
 
static void candidate_window_class_init(UIMCandidateWindowClass *klass)
170
 
{
171
 
  cand_win_gtk_signals[INDEX_CHANGED_SIGNAL]
172
 
    = g_signal_new("index-changed",
173
 
                   G_TYPE_FROM_CLASS(klass),
174
 
                   G_SIGNAL_RUN_FIRST,
175
 
                   G_STRUCT_OFFSET(UIMCandidateWindowClass, index_changed),
176
 
                   NULL, NULL,
177
 
                   g_cclosure_marshal_VOID__VOID,
178
 
                   G_TYPE_NONE, 0);
179
 
}
180
 
 
181
 
UIMCandidateWindow *
182
 
candidate_window_new(void)
183
 
{
184
 
  GObject *obj = g_object_new(UIM_TYPE_CANDIDATE_WINDOW, "type",
185
 
                  GTK_WINDOW_POPUP, NULL);
186
 
  return UIM_CANDIDATE_WINDOW(obj);
187
 
}
188
 
 
189
 
/* copied from uim-cand-win-gtk.c */
190
 
static void
191
 
update_label(UIMCandidateWindow *cwin)
192
 
{
193
 
  char label_str[20];
194
 
 
195
 
  if (cwin->candidate_index >= 0)
196
 
    g_snprintf(label_str, sizeof(label_str), "%d / %d",
197
 
               cwin->candidate_index + 1 , cwin->nr_candidates);
198
 
  else
199
 
    g_snprintf(label_str, sizeof(label_str), "- / %d",
200
 
               cwin->nr_candidates);
201
 
 
202
 
  gtk_label_set_text(GTK_LABEL(cwin->num_label), label_str);
203
 
}
204
 
 
205
 
/* copied from uim-cand-win-gtk.c */
206
 
static gboolean
207
 
tree_selection_changed(GtkTreeSelection *selection,
208
 
                       GtkTreeModel *model,
209
 
                       GtkTreePath *path,
210
 
                       gboolean path_currently_selected,
211
 
                       gpointer data)
212
 
{
213
 
  /* candidate_window *cwin = data; */
214
 
  gint *indicies;
215
 
  gint idx;
216
 
 
217
 
  if (!&cwin)
218
 
    return TRUE;
219
 
 
220
 
  indicies = gtk_tree_path_get_indices(path);
221
 
  g_return_val_if_fail(indicies, TRUE);
222
 
  idx = *indicies + cwin->display_limit * cwin->page_index;
223
 
 
224
 
  if (!path_currently_selected && cwin->candidate_index != idx) {
225
 
    if (cwin->candidate_index >= 0) {
226
 
      cwin->candidate_index = idx;
227
 
      g_signal_emit(G_OBJECT(cwin),
228
 
                    cand_win_gtk_signals[INDEX_CHANGED_SIGNAL], 0);
229
 
    }
230
 
 
231
 
    update_label(cwin);
232
 
 
233
 
    if (cwin->candidate_index < 0)
234
 
      return FALSE;
235
 
    else
236
 
      return TRUE;
237
 
  } else {
238
 
    update_label(cwin);
239
 
 
240
 
    return TRUE;
241
 
  }
242
 
}
243
 
 
244
 
#if 0
245
 
/* copied from uim-cand-win-gtk.c */
246
 
static gboolean
247
 
tree_view_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
248
 
{
249
 
  GtkTreePath *path;
250
 
  gboolean exist, retval = FALSE;
251
 
  gint *indicies;
252
 
 
253
 
  fprintf(stderr, "tree_view_button_press\n");
254
 
  g_return_val_if_fail(GTK_IS_TREE_VIEW(widget), FALSE);
255
 
  g_return_val_if_fail(UIM_CANDIDATE_WINDOW(data), FALSE);
256
 
 
257
 
  /* cwin = UIM_CANDIDATE_WINDOW(data); */
258
 
 
259
 
  exist = gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
260
 
                                        event->x, event->y,
261
 
                                        &path, NULL, NULL, NULL);
262
 
  if (!exist)
263
 
    return FALSE;
264
 
 
265
 
  indicies = gtk_tree_path_get_indices(path);
266
 
 
267
 
  /* don't relay button press event to empty row */
268
 
  if (cwin->display_limit * cwin->page_index + *indicies >= cwin->nr_candidates)
269
 
 
270
 
    retval = TRUE;
271
 
 
272
 
  gtk_tree_path_free(path);
273
 
 
274
 
  return retval;
275
 
}
276
 
#endif
277
 
 
278
 
static void
279
 
cb_tree_view_destroy(GtkWidget *widget, GPtrArray *stores)
280
 
{
281
 
  gint i;
282
 
 
283
 
  g_return_if_fail(GTK_IS_TREE_VIEW(widget));
284
 
 
285
 
  for (i = cwin->stores->len - 1; i >= 0; i--) {
286
 
    GtkListStore *store = g_ptr_array_remove_index(cwin->stores, i);
287
 
    gtk_list_store_clear(store);
288
 
    g_object_unref(G_OBJECT(store));
289
 
  }
290
 
  g_ptr_array_free(cwin->stores, TRUE);
291
 
}
292
 
 
293
 
static void
294
 
init_candidate_win(void) {
295
 
  cwin = candidate_window_new();
296
 
  g_signal_connect(G_OBJECT(cwin), "index-changed",
297
 
                   G_CALLBACK(index_changed_cb), NULL);
298
 
  g_signal_connect(G_OBJECT(cwin), "configure_event",
299
 
                   G_CALLBACK(configure_event_cb), NULL);
300
 
}
301
 
 
302
 
static void
303
 
candidate_window_init(UIMCandidateWindow *cwin)
304
 
{
305
 
  GtkCellRenderer *renderer;
306
 
  GtkTreeViewColumn *column; 
307
 
  GtkWidget *scrolled_window;
308
 
  GtkWidget *vbox;
309
 
  GtkWidget *frame;
310
 
  GtkTreeSelection *selection;
311
 
  GdkRectangle cursor_location;
312
 
  
313
 
  vbox = gtk_vbox_new(FALSE, 0);
314
 
  frame = gtk_frame_new(NULL);
315
 
 
316
 
  cwin->stores = g_ptr_array_new();
317
 
  
318
 
  gtk_window_set_default_size(GTK_WINDOW(cwin),
319
 
                  CANDWIN_DEFAULT_WIDTH, -1);
320
 
  
321
 
 
322
 
  scrolled_window = gtk_scrolled_window_new(NULL, NULL);
323
 
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
324
 
                                 GTK_POLICY_NEVER,
325
 
                                 GTK_POLICY_NEVER);
326
 
  gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
327
 
  
328
 
  cwin->view = gtk_tree_view_new();
329
 
  g_signal_connect(G_OBJECT(cwin->view), "destroy", 
330
 
                   G_CALLBACK(cb_tree_view_destroy), cwin->stores);
331
 
  gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(cwin->view), TRUE);
332
 
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cwin->view), FALSE);
333
 
  gtk_container_add(GTK_CONTAINER(scrolled_window), cwin->view);
334
 
 
335
 
  gtk_container_add(GTK_CONTAINER(frame), vbox);
336
 
  gtk_container_add(GTK_CONTAINER(cwin), frame);
337
 
  gtk_container_set_border_width(GTK_CONTAINER(frame), 0);
338
 
    
339
 
  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cwin->view));
340
 
 
341
 
  gtk_tree_selection_set_select_function(selection,
342
 
                                         tree_selection_changed,
343
 
                                         cwin,
344
 
                                         NULL);
345
 
 
346
 
  renderer = gtk_cell_renderer_text_new();
347
 
  g_object_set(renderer, "scale", 1.2, NULL);
348
 
 
349
 
  column = gtk_tree_view_column_new_with_attributes("No",
350
 
                                                    renderer,
351
 
                                                    "text",
352
 
                                                    COLUMN_HEADING,
353
 
                                                    NULL);
354
 
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
355
 
  gtk_tree_view_append_column(GTK_TREE_VIEW(cwin->view), column);
356
 
  
357
 
  renderer = gtk_cell_renderer_text_new();
358
 
  g_object_set(renderer, "scale", 1.2, NULL);
359
 
  /* g_object_set(renderer, "size-points", 20.0, NULL); */
360
 
  column = gtk_tree_view_column_new_with_attributes("Text",
361
 
                                                    renderer,
362
 
                                                    "text",
363
 
                                                    COLUMN_CANDIDATE,
364
 
                                                    NULL);
365
 
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
366
 
  gtk_tree_view_append_column(GTK_TREE_VIEW(cwin->view), column);
367
 
  
368
 
  cwin->num_label = gtk_label_new("");
369
 
 
370
 
  gtk_box_pack_start(GTK_BOX(vbox), cwin->num_label, FALSE, FALSE, 0);
371
 
 
372
 
#if 0
373
 
  g_signal_connect(G_OBJECT(cwin->view), "button-press-event", 
374
 
                   G_CALLBACK(tree_view_button_press), cwin);
375
 
#endif
376
 
 
377
 
  cwin->pos_x = 0;
378
 
  cwin->pos_y = 0;
379
 
  cwin->is_active = FALSE;
380
 
  cwin->caret_state_indicator = caret_state_indicator_new();
381
 
 
382
 
  cursor_location.x = 0;
383
 
  cursor_location.y = 0;
384
 
  cursor_location.height = 0;
385
 
  caret_state_indicator_set_cursor_location(cwin->caret_state_indicator, &cursor_location);
386
 
}
387
 
 
388
 
static void
389
 
candwin_activate(gchar **str)
390
 
{
391
 
  gsize rbytes, wbytes;
392
 
  gint i, nr_stores = 1;
393
 
  guint j = 1;
394
 
  gchar *utf8_str;
395
 
  const gchar *charset;
396
 
  guint display_limit;
397
 
  GSList *candidates = NULL;
398
 
 
399
 
  if (cwin->stores == NULL)
400
 
    cwin->stores = g_ptr_array_new();
401
 
 
402
 
  /* remove old data */
403
 
  for (i = cwin->stores->len - 1; i >= 0; i--) {
404
 
    GtkListStore *store = g_ptr_array_remove_index(cwin->stores, i);
405
 
    gtk_list_store_clear(store);
406
 
    g_object_unref(G_OBJECT(store));
407
 
  }
408
 
 
409
 
  if (!strncmp(str[1], "charset=", 8))
410
 
    charset = str[1] + 8;
411
 
  else
412
 
    charset = "UTF-8";
413
 
 
414
 
  if (!strncmp(str[2], "display_limit=", 14)) {
415
 
    display_limit = atoi(str[2] + 14);
416
 
    i = 3;
417
 
  } else {
418
 
    display_limit = 0;
419
 
    i = 2;
420
 
  }
421
 
 
422
 
  for ( ; str[i]; i++) {
423
 
    if (strcmp(str[i], "") == 0) {
424
 
      break;
425
 
    }
426
 
    utf8_str = g_convert(str[i],
427
 
                         -1, 
428
 
                         "UTF-8",
429
 
                         charset,
430
 
                         &rbytes, &wbytes, NULL);
431
 
    
432
 
    candidates = g_slist_append(candidates, utf8_str);
433
 
    j++;
434
 
  }
435
 
 
436
 
  cwin->candidate_index = -1;
437
 
  cwin->nr_candidates = j - 1;
438
 
  cwin->display_limit = display_limit;
439
 
 
440
 
  if (candidates == NULL)
441
 
    return;
442
 
 
443
 
  /* calculate number of GtkListStores to create */
444
 
  if (display_limit) {
445
 
    nr_stores = cwin->nr_candidates / display_limit;
446
 
    if (cwin->nr_candidates > display_limit * nr_stores)
447
 
      nr_stores++;
448
 
  }
449
 
 
450
 
  /* create GtkListStores, and set candidates */
451
 
  for (i = 0; i < nr_stores; i++) {
452
 
    GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
453
 
    GSList *node;
454
 
 
455
 
    g_ptr_array_add(cwin->stores, store);
456
 
 
457
 
    /* set candidates */
458
 
    for (j = i * display_limit, node = g_slist_nth(candidates, j);
459
 
         display_limit ? j < display_limit * (i + 1) : j < cwin->nr_candidates;
460
 
         j++, node = g_slist_next(node))
461
 
    {
462
 
      GtkTreeIter ti;
463
 
      if (node) {
464
 
        gchar *str = node->data;
465
 
        gchar **column = g_strsplit(str, "\t", 2);
466
 
        gtk_list_store_append(store, &ti);
467
 
        gtk_list_store_set(store, &ti,
468
 
                           COLUMN_HEADING, column[0],
469
 
                           COLUMN_CANDIDATE, column[1],
470
 
                           TERMINATOR);
471
 
        g_strfreev(column);
472
 
        g_free(str);
473
 
      } else {
474
 
        /* No need to set any data for empty row. */
475
 
      }
476
 
    }
477
 
  }
478
 
 
479
 
  uim_cand_win_gtk_set_page(cwin, 0);
480
 
  update_label(cwin);
481
 
 
482
 
  gtk_widget_show_all(GTK_WIDGET(cwin));
483
 
  cwin->is_active = TRUE;
484
 
}
485
 
 
486
 
static void
487
 
candwin_update(gchar **str)
488
 
{
489
 
  int index;
490
 
  sscanf(str[1], "%d", &index);
491
 
 
492
 
  uim_cand_win_gtk_set_index(cwin, index);
493
 
}
494
 
 
495
 
static void
496
 
candwin_move(char **str)
497
 
{
498
 
  sscanf(str[1], "%d", &cwin->pos_x);
499
 
  sscanf(str[2], "%d", &cwin->pos_y);
500
 
 
501
 
  uim_cand_win_gtk_layout();
502
 
}
503
 
 
504
 
static void
505
 
candwin_show(void)
506
 
{
507
 
  if (cwin->is_active)
508
 
    gtk_widget_show_all(GTK_WIDGET(cwin));
509
 
}
510
 
 
511
 
static void
512
 
candwin_deactivate(void)
513
 
{
514
 
  gtk_widget_hide(GTK_WIDGET(cwin));
515
 
  cwin->is_active = FALSE;
516
 
}
517
 
 
518
 
static void
519
 
caret_state_show(gchar **str)
520
 
{
521
 
  int timeout;
522
 
 
523
 
  sscanf(str[1], "%d", &timeout);
524
 
  caret_state_indicator_update(cwin->caret_state_indicator, cwin->pos_x, cwin->pos_y, str[2]);
525
 
  if (timeout != 0)
526
 
    caret_state_indicator_set_timeout(cwin->caret_state_indicator, timeout * 1000);
527
 
  gtk_widget_show_all(GTK_WIDGET(cwin->caret_state_indicator));
528
 
}
529
 
 
530
 
static void
531
 
caret_state_update()
532
 
{
533
 
  caret_state_indicator_update(cwin->caret_state_indicator, cwin->pos_x, cwin->pos_y, NULL);
534
 
}
535
 
 
536
 
static void
537
 
caret_state_hide()
538
 
{
539
 
  gtk_widget_hide(cwin->caret_state_indicator);
540
 
}
541
 
 
542
 
static void str_parse(gchar *str)
543
 
{
544
 
  gchar **tmp;
545
 
  gchar *command;
546
 
 
547
 
  tmp = g_strsplit(str, "\n", 0);
548
 
  command = tmp[0];
549
 
 
550
 
  if (command) {
551
 
    if (strcmp("activate", command) == 0) {
552
 
      candwin_activate(tmp);
553
 
    } else if (strcmp("select", command) == 0) {
554
 
      candwin_update(tmp);
555
 
    } else if (strcmp("show", command) == 0) {
556
 
      candwin_show();
557
 
    } else if (strcmp("hide", command) == 0) {
558
 
      gtk_widget_hide_all(GTK_WIDGET(cwin));
559
 
    } else if (strcmp("move", command) == 0) {
560
 
      candwin_move(tmp);
561
 
    } else if (strcmp("deactivate", command) == 0) {
562
 
      candwin_deactivate();
563
 
    } else if (strcmp("show_caret_state", command) == 0) {
564
 
      caret_state_show(tmp);
565
 
    } else if (strcmp("update_caret_state", command) == 0) {
566
 
      caret_state_update();
567
 
    } else if (strcmp("hide_caret_state", command) == 0) {
568
 
      caret_state_hide();
569
 
    }
570
 
  }
571
 
  g_strfreev(tmp);
572
 
}
573
 
 
574
 
#define CANDIDATE_BUFFER_SIZE   4096
575
 
static gboolean
576
 
read_cb(GIOChannel *channel, GIOCondition c, gpointer p)
577
 
{
578
 
  char buf[CANDIDATE_BUFFER_SIZE];
579
 
  char *read_buf = strdup("");
580
 
  int i = 0;
581
 
  int n;
582
 
  gchar **tmp;
583
 
  int fd = g_io_channel_unix_get_fd(channel);
584
 
 
585
 
  while (uim_helper_fd_readable(fd) > 0) {
586
 
    n = read(fd, buf, CANDIDATE_BUFFER_SIZE - 1);
587
 
    if (n == 0) {
588
 
      close(fd);
589
 
      exit(EXIT_FAILURE);
590
 
    }
591
 
    if (n == -1)
592
 
      return TRUE;
593
 
    buf[n] = '\0';
594
 
    read_buf = realloc(read_buf, strlen(read_buf) + n + 1);
595
 
    strcat(read_buf, buf);
596
 
  }
597
 
 
598
 
  tmp = g_strsplit(read_buf, "\n\n", 0);
599
 
 
600
 
  while (tmp[i]) {
601
 
    str_parse(tmp[i]);
602
 
    i++;
603
 
  }
604
 
  g_strfreev(tmp);
605
 
  free(read_buf);
606
 
  return TRUE;
607
 
}
608
 
 
609
 
int
610
 
main(int argc, char *argv[])
611
 
{
612
 
  GIOChannel *channel;
613
 
 
614
 
  gtk_set_locale();
615
 
  gtk_init(&argc, &argv);
616
 
 
617
 
  init_candidate_win();
618
 
 
619
 
  channel = g_io_channel_unix_new(0);
620
 
  read_tag = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
621
 
                            read_cb, 0);
622
 
  g_io_channel_unref(channel);
623
 
 
624
 
  gtk_main();
625
 
  return 0;
626
 
}
627
 
 
628
 
/* copied from uim-cand-win-gtk.c */
629
 
static gint
630
 
uim_cand_win_gtk_get_index(UIMCandidateWindow *cwin)
631
 
{
632
 
  g_return_val_if_fail(UIM_IS_CANDIDATE_WINDOW(cwin), -1);
633
 
 
634
 
  return cwin->candidate_index;
635
 
}
636
 
 
637
 
/* copied from uim-cand-win-gtk.c */
638
 
static void
639
 
uim_cand_win_gtk_set_index(UIMCandidateWindow *cwin, gint index)
640
 
{
641
 
  gint new_page;
642
 
 
643
 
  g_return_if_fail(UIM_IS_CANDIDATE_WINDOW(cwin));
644
 
 
645
 
  if (index >= (gint) cwin->nr_candidates)
646
 
    cwin->candidate_index = 0;
647
 
  else
648
 
    cwin->candidate_index = index;
649
 
 
650
 
  if (cwin->candidate_index >= 0 && cwin->display_limit)
651
 
    new_page = cwin->candidate_index / cwin->display_limit;
652
 
  else
653
 
    new_page = cwin->page_index;
654
 
 
655
 
  if (cwin->page_index != new_page)
656
 
    uim_cand_win_gtk_set_page(cwin, new_page);
657
 
 
658
 
  if (cwin->candidate_index >= 0) {
659
 
    GtkTreePath *path;
660
 
    gint pos = index;
661
 
 
662
 
    if (cwin->display_limit)
663
 
      pos = cwin->candidate_index % cwin->display_limit;
664
 
 
665
 
    path = gtk_tree_path_new_from_indices(pos, -1);
666
 
    gtk_tree_view_set_cursor(GTK_TREE_VIEW(cwin->view),
667
 
                             path, NULL, FALSE);
668
 
    gtk_tree_path_free(path);
669
 
 
670
 
  } else {
671
 
    GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cwin
672
 
->view));
673
 
 
674
 
    gtk_tree_selection_unselect_all(selection);
675
 
  }
676
 
}
677
 
 
678
 
/* copied from uim-cand-win-gtk.c */
679
 
static void
680
 
uim_cand_win_gtk_set_page(UIMCandidateWindow *cwin, gint page)
681
 
{
682
 
  guint len, new_page;
683
 
  gint new_index;
684
 
 
685
 
  g_return_if_fail(UIM_IS_CANDIDATE_WINDOW(cwin));
686
 
  g_return_if_fail(cwin->stores);
687
 
 
688
 
  len = cwin->stores->len;
689
 
  g_return_if_fail(len);
690
 
 
691
 
  if (page < 0) {
692
 
    gtk_tree_view_set_model(GTK_TREE_VIEW(cwin->view),
693
 
                            GTK_TREE_MODEL(cwin->stores->pdata[len - 1]));
694
 
    new_page = len - 1;
695
 
  } else if (page >= (gint) len) {
696
 
    gtk_tree_view_set_model(GTK_TREE_VIEW(cwin->view),
697
 
                            GTK_TREE_MODEL(cwin->stores->pdata[0]));
698
 
    new_page = 0;
699
 
  } else {
700
 
    gtk_tree_view_set_model(GTK_TREE_VIEW(cwin->view),
701
 
 
702
 
                            GTK_TREE_MODEL(cwin->stores->pdata[page]));
703
 
    new_page = page;
704
 
  }
705
 
 
706
 
  cwin->page_index = new_page;
707
 
 
708
 
  if (cwin->display_limit) {
709
 
    if (cwin->candidate_index >= 0)
710
 
      new_index
711
 
        = (new_page * cwin->display_limit) + (cwin->candidate_index % cwin->display_limit);
712
 
    else
713
 
      new_index = -1;
714
 
  } else {
715
 
    new_index = cwin->candidate_index;
716
 
  }
717
 
 
718
 
  if (new_index >= (gint) cwin->nr_candidates)
719
 
    new_index = cwin->nr_candidates - 1;
720
 
 
721
 
 /* shrink the window */
722
 
  gtk_window_resize(GTK_WINDOW(cwin), CANDWIN_DEFAULT_WIDTH, 1);
723
 
 
724
 
  uim_cand_win_gtk_set_index(cwin, new_index);
725
 
}
726
 
 
727
 
static void
728
 
uim_cand_win_gtk_layout()
729
 
{
730
 
  int x, y;
731
 
  int screen_width, screen_height;
732
 
 
733
 
  screen_width = gdk_screen_get_width(gdk_screen_get_default());
734
 
  screen_height = gdk_screen_get_height(gdk_screen_get_default());
735
 
 
736
 
  if (screen_width < cwin->pos_x + cwin->width)
737
 
    x = cwin->pos_x - cwin->width;
738
 
  else
739
 
    x = cwin->pos_x;
740
 
 
741
 
  if (screen_height < cwin->pos_y + cwin->height)
742
 
    y = cwin->pos_y - cwin->height - 20; /* FIXME: Preedit height is needed to
743
 
                                            be sent by uim-xim */
744
 
  else
745
 
    y = cwin->pos_y;
746
 
 
747
 
  gtk_window_move(GTK_WINDOW(cwin), x, y);
748
 
}
749
 
 
750
 
static gboolean
751
 
configure_event_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
752
 
{
753
 
  cwin->width = event->width;
754
 
  cwin->height = event->height;
755
 
 
756
 
  uim_cand_win_gtk_layout();
757
 
 
758
 
  return FALSE;
759
 
}