Back to index

im-sdk  12.3.91
unicode_char_info.c
Go to the documentation of this file.
00001 #include <gtk/gtk.h>
00002 #include "unicode_char_info_marshal.h"
00003 #include "unicode_char_info.h"
00004 
00005 static void unicharinfo_table_class_init (UniCharInfoClass *class);
00006 static void unicharinfo_init (UniCharInfo *obj);
00007 static gint expose_event_handler (GtkWidget *, GdkEventExpose *, UniCharInfo *);
00008 static void draw_unichar_table (UniCharInfo *obj);
00009 static void draw_trellis (UniCharInfo *);
00010 
00011 static void size_allocate_handler (GtkWidget *, GtkAllocation *, UniCharInfo *);
00012 
00013 static gint minimal_column_width (UniCharInfo *obj);
00014 static gint minimal_row_height (UniCharInfo *obj);
00015 
00016 static gint bare_minimal_char_width (UniCharInfo *obj);
00017 static gint bare_minimal_char_height (UniCharInfo *obj);
00018 static gint __font_height (PangoFontMetrics *fm);
00019 
00020 static gunichar rowcol_to_unichar (UniCharInfo *, gint , gint);
00021 static void charinfo_table_draw_character (UniCharInfo *, gint, gint);
00022 static gboolean __unichar_is_valid (gunichar uc);
00023 static GtkWidget *get_scrollbar (UniCharInfo *obj);
00024 static void charinfo_table_redraw (UniCharInfo *obj);
00025 
00026 static void
00027 debug_print_width (UniCharInfo *obj);
00028 enum {
00029   ACTIVATE = 0,
00030   SET_ACTIVE_CHAR,
00031   NUM_SIGNALS
00032 };
00033 
00034 static guint unicharinfo_table_signals[NUM_SIGNALS] = { 0, 0};
00035 
00036 GType
00037 unicharinfo_get_type (void)
00038 {
00039   static GType unicharinfo_type = 0;
00040   if (!unicharinfo_type){
00041     static const GTypeInfo unicharinfo_info = {
00042       sizeof (UniCharInfoClass),
00043       NULL, /* base init */
00044       NULL, /* base finalize */
00045       (GClassInitFunc) unicharinfo_table_class_init, /* class init */
00046       NULL, /* class finalize */
00047       NULL, /* class data */
00048       sizeof (UniCharInfo),
00049       0,
00050       (GInstanceInitFunc) unicharinfo_init, /* obj init */
00051       NULL /* value table */
00052     };
00053     unicharinfo_type =
00054       g_type_register_static (GTK_TYPE_HBOX, "unicharinfo",
00055                            &unicharinfo_info, 0);
00056   }
00057   return unicharinfo_type;
00058 }
00059 
00060 static GtkWidget *
00061 get_scrollbar (UniCharInfo *obj)
00062 {
00063   obj->adjustment =
00064     gtk_adjustment_new ( 0.0,
00065                       0.0, 1.0 * 0xFFFF / obj->n_cols,
00066                       2.0, 3.0 * obj->n_rows,
00067                       0.0);
00068   return gtk_vscrollbar_new (GTK_ADJUSTMENT (obj->adjustment));
00069 }
00070 static void
00071 unicharinfo_table_class_init (UniCharInfoClass *class)
00072 {
00073   class->set_active_char = NULL;
00074   
00075   unicharinfo_table_signals[SET_ACTIVE_CHAR] =
00076     g_signal_new ("set_active_char", unicharinfo_get_type(),
00077                 G_SIGNAL_RUN_FIRST,
00078                 G_STRUCT_OFFSET (UniCharInfoClass, set_active_char),
00079                 NULL, NULL, unicharinfo_table_marshal_VOID__UINT, G_TYPE_NONE,
00080                 1, G_TYPE_UINT);
00081 
00082 }
00083 
00084 static void
00085 unicharinfo_init (UniCharInfo *obj)
00086 {
00087   PangoContext *pango_ctx;
00088 #if 0
00089   obj->n_rows = 10;
00090   obj->n_cols = 0x10;
00091 #endif
00092   obj->begin_char = 0xac00;
00093   obj->end_char = 0xac30;
00094   obj->first_char = 0xac00;
00095   
00096   obj->drawing_area = gtk_drawing_area_new ();
00097 
00098   gtk_widget_set_events
00099     (obj->drawing_area,
00100      GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
00101      GDK_SCROLL_MASK);
00102   g_signal_connect (G_OBJECT (obj->drawing_area), "expose-event",
00103                   G_CALLBACK (expose_event_handler), obj);
00104   g_signal_connect (G_OBJECT (obj->drawing_area), "size-allocate",
00105                   G_CALLBACK (size_allocate_handler), obj);
00106 
00107   pango_ctx = gtk_widget_get_pango_context (obj->drawing_area);
00108   obj->pango_fm =
00109     pango_context_get_metrics (
00110                             pango_ctx,
00111                             obj->drawing_area->style->font_desc, NULL);
00112   obj->pango_layout = pango_layout_new (pango_ctx);
00113   pango_layout_set_font_description (obj->pango_layout,
00114                                  obj->drawing_area->style->font_desc);
00115                             
00116   gtk_box_pack_start (GTK_BOX (obj), obj->drawing_area, TRUE, TRUE, 0);
00117   gtk_box_pack_start (GTK_BOX (obj), get_scrollbar (obj), FALSE, FALSE, 0);
00118 
00119   gtk_widget_show (obj->drawing_area);
00120   
00121 #if 0
00122   {
00123     int i,j;
00124     int n_families, n_faces;
00125     PangoFontFamily **families = NULL;
00126     PangoFontFace **faces = NULL;
00127     pango_context_list_families (pango_ctx ,&families, &n_families);
00128     for (i = 0 ; i < n_families; i++){
00129       g_printf ("******** family %d ******\n", i);
00130       faces = NULL;
00131       pango_font_family_list_faces (families[i], &faces, &n_faces);
00132       for (j = 0 ; j < n_faces; j++){
00133        g_printf
00134          ("face name : %s\n", pango_font_face_get_face_name (faces[j]));
00135       }
00136     }
00137   }
00138 #endif
00139 }
00140 
00141 GtkWidget *
00142 unicharinfo_new (void)
00143 {
00144   return GTK_WIDGET (g_object_new (unicharinfo_get_type (), NULL));
00145 }
00146 
00147 static gint
00148 expose_event_handler (GtkWidget *widget,
00149                     GdkEventExpose *event,
00150                     UniCharInfo *obj)
00151 {
00152   gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
00153   
00154   if (obj->pixmap == NULL){
00155     draw_unichar_table (obj);
00156   }
00157   gdk_draw_pixmap (obj->drawing_area->window,
00158                  widget->style->fg_gc[GTK_STATE_NORMAL],
00159                  obj->pixmap,
00160                  event->area.x, event->area.y,
00161                  event->area.x, event->area.y,
00162                  event->area.width, event->area.height);
00163   debug_print_width (obj);
00164 #if 0
00165   g_printf ("I was called\n");
00166 #endif
00167 }
00168 
00169 static void
00170 size_allocate_handler (GtkWidget *widget, 
00171                      GtkAllocation *allocation, 
00172                      UniCharInfo *obj)
00173 {
00174   gint old_rows, old_cols;
00175   old_rows = obj->n_rows;
00176   old_cols = obj->n_cols;
00177 
00178   obj->n_cols = (allocation->width - 1) / bare_minimal_char_width (obj);
00179   obj->n_rows = (allocation->height - 1) / bare_minimal_char_height (obj);
00180 
00181   if (obj->n_cols < 1)
00182     obj->n_cols = 1;
00183   if (obj->n_rows < 1)
00184     obj->n_rows = 1;
00185   
00186   if (obj->pixmap != NULL)
00187     g_object_unref (obj->pixmap);
00188   obj->pixmap = NULL;
00189   
00190   if (obj->n_rows == old_rows && obj->n_cols == old_cols)
00191     return;
00192 #if 0
00193   g_printf ("size_allocate_handler was called(%d col, %d rows)\n",
00194            obj->n_cols, obj->n_rows);
00195 #endif
00196 }
00197 
00198 static void
00199 debug_print_width (UniCharInfo *obj)
00200 {
00201   int i;
00202   int colwidth;
00203   int offset;
00204   int local_offset = 0;
00205   
00206   for (i = 0; i < obj->n_cols; i++){
00207     colwidth = charinfo_table_column_width (obj, i);
00208     offset = charinfo_table_x_offset (obj, i);
00209 
00210     
00211     g_printf ("col %d: width : %d, offset: %d: loffset: %d(%d)\n",
00212              i, colwidth, offset, local_offset, offset - local_offset);
00213     local_offset += offset;
00214 
00215   }
00216 }
00217 static void
00218 draw_unichar_table (UniCharInfo *obj)
00219 {
00220   gint row, col;
00221   if (obj->pixmap == NULL){
00222     obj->pixmap =
00223       gdk_pixmap_new (obj->drawing_area->window,
00224                     obj->drawing_area->allocation.width,
00225                     obj->drawing_area->allocation.height,
00226                     -1);
00227   }
00228   gdk_draw_rectangle (obj->pixmap,
00229                     obj->drawing_area->style->base_gc[GTK_STATE_NORMAL],
00230                     TRUE,
00231                     0, 0,
00232                     obj->drawing_area->allocation.width,
00233                     obj->drawing_area->allocation.height);
00234   draw_trellis (obj);
00235 
00236   for (row = 0; row < obj->n_rows; row++)
00237     for (col = 0; col < obj->n_cols; col++){
00238       charinfo_table_draw_character (obj, row, col);
00239     }
00240 }
00241 
00242 static void
00243 set_current_char (UniCharInfo *obj, gunichar uc)
00244 {
00245   gint offset;
00246 
00247   g_return_if_fail (uc >= 0 && uc <= UNICHAR_MAX);
00248 
00249   obj->previous_selected_char = obj->selected_char;
00250   obj->previous_first_char = obj->first_char;
00251 
00252   obj->selected_char = uc;
00253 
00254   if (uc - obj->first_char >= obj->n_rows * obj->n_cols){
00255     offset = (gint) obj->selected_char - (gint) obj->previous_selected_char;
00256     if ((gint) obj->previous_first_char + offset >= 0)
00257       obj->first_char = obj->first_char + offset;
00258     else
00259       obj->first_char = 0;
00260     obj->first_char -= (obj->first_char % obj->n_cols);
00261 
00262     if (obj->selected_char - obj->first_char >= obj->n_rows * obj->n_cols)
00263       obj->first_char += obj->n_cols;
00264   }
00265 
00266   g_signal_emit (obj,
00267                unicharinfo_table_signals[SET_ACTIVE_CHAR],
00268                0 , obj->selected_char);
00269   
00270     
00271 }
00272 
00273 
00274 static void
00275 charinfo_table_draw_character (UniCharInfo *obj, gint row, gint col)
00276 {
00277   gint padding_x, padding_y;
00278   gint char_width, char_height;
00279   gint square_width, square_height; 
00280   gunichar uc;
00281   GdkGC *gc;
00282   gchar buf[10];
00283   gint n;
00284 
00285   uc = rowcol_to_unichar (obj, row, col);
00286 
00287   /* need to review later... */
00288 #if 0  
00289   if (uc < 0 || uc > UNICHAR_MAX || ! __unichar_is_valid (uc) )
00290     return;
00291 
00292 
00293   if (GTK_WIDGET_HAS_FOCUS (obj->drawing_area) 
00294       && uc == obj->selected_char)
00295     gc = obj->drawing_area->style->text_gc[GTK_STATE_SELECTED];
00296   else if (uc == obj->selected_char)
00297     gc = obj->drawing_area->style->text_gc[GTK_STATE_ACTIVE];
00298   else
00299     gc = obj->drawing_area->style->text_gc[GTK_STATE_NORMAL];
00300 #endif
00301   
00302   gc = obj->drawing_area->style->text_gc[GTK_STATE_NORMAL];
00303   
00304   square_width = charinfo_table_column_width (obj, col) - 1;
00305   square_height = charinfo_table_row_height (obj, row) - 1;
00306   
00307   g_printf ("(%d, %d)-width(%d), height(%d)\n",
00308            row, col, square_width, square_height);
00309 
00310   n = charinfo_unichar_to_printable_utf8 (uc, buf);
00311   pango_layout_set_text (obj->pango_layout, buf, n);
00312 
00313   pango_layout_get_pixel_size (obj->pango_layout, 
00314                                &char_width, &char_height);
00315 
00316   /* (square_width - char_width)/2 is the smaller half */
00317   padding_x = (square_width - char_width) - (square_width - char_width)/2;
00318   padding_y = (square_height - char_height) - (square_height - char_height)/2;
00319 
00320   gdk_draw_layout (obj->pixmap, gc,
00321                    charinfo_table_x_offset (obj, col) + padding_x,
00322                    charinfo_table_y_offset (obj, row) + padding_y,
00323                    obj->pango_layout);
00324 }
00325 
00326 gint
00327 charinfo_table_x_offset (UniCharInfo *obj, gint col)
00328 {
00329   gint i, offset = 0;
00330   for (i = 0; i < col; i++){
00331     offset +=  charinfo_table_column_width (obj, col);
00332     
00333   }
00334   return offset;
00335 }
00336 
00337 gint
00338 charinfo_table_y_offset (UniCharInfo *obj, gint row)
00339 {
00340   gint r, offset = 0;
00341 
00342   for (r = 0 ;  r < row;  r++)
00343     offset += charinfo_table_row_height (obj, r);
00344 
00345   return offset;
00346 }
00347 
00348 static gunichar
00349 rowcol_to_unichar (UniCharInfo *obj, gint row, gint col)
00350 {
00351   if (gtk_widget_get_direction (obj->drawing_area) == GTK_TEXT_DIR_RTL)
00352     return obj->first_char + row * obj->n_cols 
00353            + (obj->n_cols - col - 1);
00354   else
00355     return obj->first_char + row * obj->n_cols + col;
00356 }
00357 
00358 
00359 gint
00360 charinfo_unichar_to_printable_utf8 (gunichar uc, gchar *outbuf)
00361 {
00362 #if 0
00363   if (! gucharmap_unichar_validate (uc) || (! gucharmap_unichar_isgraph (uc) 
00364       && gucharmap_unichar_type (uc) != G_UNICODE_PRIVATE_USE))
00365     return 0;
00366   else if (gucharmap_unichar_type (uc) == G_UNICODE_COMBINING_MARK
00367       || gucharmap_unichar_type (uc) == G_UNICODE_ENCLOSING_MARK
00368       || gucharmap_unichar_type (uc) == G_UNICODE_NON_SPACING_MARK)
00369     {
00370       gint x;
00371 
00372       outbuf[0] = ' ';
00373       outbuf[1] = '\xe2'; /* ZERO */ 
00374       outbuf[2] = '\x80'; /* WIDTH */
00375       outbuf[3] = '\x8d'; /* JOINER (0x200D) */
00376 
00377       x = g_unichar_to_utf8 (uc, outbuf + 4);
00378 
00379       return x + 4;
00380     }
00381   else
00382     return g_unichar_to_utf8 (uc, outbuf);
00383 #endif
00384   return g_unichar_to_utf8 (uc, outbuf);
00385 }
00386 
00387 static void
00388 draw_trellis (UniCharInfo *obj)
00389 {
00390   gint x, y;
00391   gint i_col, i_row;
00392   gdk_draw_line (obj->pixmap,
00393                obj->drawing_area->style->dark_gc[GTK_STATE_NORMAL],
00394                0, 0, 0, obj->drawing_area->allocation.height - 1);
00395 
00396   for (x = 0, i_col = 0; i_col < obj->n_cols; i_col++){
00397     x += charinfo_table_column_width (obj, i_col);
00398     gdk_draw_line (obj->pixmap,
00399                  obj->drawing_area->style->dark_gc[GTK_STATE_NORMAL],
00400                  x,0,x, obj->drawing_area->allocation.height - 1);
00401   }
00402 
00403   gdk_draw_line (obj->pixmap,
00404                obj->drawing_area->style->dark_gc[GTK_STATE_NORMAL],
00405                0, 0, obj->drawing_area->allocation.width - 1, 0);
00406   for (y = 0, i_row = 0; i_row < obj->n_rows; i_row++){
00407     y += charinfo_table_row_height (obj, i_row);
00408     gdk_draw_line (obj->pixmap,
00409                  obj->drawing_area->style->dark_gc[GTK_STATE_NORMAL],
00410                  0, y, obj->drawing_area->allocation.width - 1, y);
00411   }
00412 }
00413 
00414 static gint
00415 minimal_column_width (UniCharInfo *obj)
00416 {
00417   gint padding;
00418   gint char_glyph_width;
00419   char_glyph_width = bare_minimal_char_width (obj);
00420   padding =
00421     (obj->drawing_area->allocation.width -
00422      (obj->n_cols * char_glyph_width + 1)) / obj->n_cols;
00423 #if 0
00424   g_printf ("minimal_column_width : %d\n", padding + char_glyph_width);
00425 #endif
00426   return padding + char_glyph_width;
00427 }
00428 
00429 static gint
00430 minimal_row_height (UniCharInfo *obj)
00431 {
00432   gint padding;
00433   gint char_glyph_height;
00434   char_glyph_height = bare_minimal_char_height (obj);
00435   padding =
00436     (obj->drawing_area->allocation.height -
00437      (obj->n_rows * char_glyph_height + 1)) / obj->n_rows;
00438 #if 0
00439   g_printf ("minimal_row_height : %d\n", padding + char_glyph_height);
00440 #endif
00441   return padding + char_glyph_height;
00442 }
00443 
00444 static gint
00445 bare_minimal_char_width (UniCharInfo *obj)
00446 {
00447   return __font_height (obj->pango_fm) + 7;
00448 }
00449 
00450 static gint
00451 bare_minimal_char_height (UniCharInfo *obj)
00452 {
00453   return __font_height (obj->pango_fm) + 7;
00454 }
00455 
00456 static gint
00457 __font_height (PangoFontMetrics *fm)
00458 {
00459   gint font_height;
00460   font_height = pango_font_metrics_get_ascent (fm) +
00461     pango_font_metrics_get_descent (fm);
00462   return PANGO_PIXELS (font_height);
00463 }
00464 
00465 
00466 static gboolean
00467 __unichar_is_valid (gunichar uc)
00468 {
00469 #if 0
00470   return gucharmap_unichar_type (uc) != G_UNICODE_UNASSIGNED;
00471 #endif
00472 }
00473 
00474 gint
00475 charinfo_table_column_width (UniCharInfo *obj, gint col)
00476 {
00477   gint num_padded_columns;
00478   gint min_col_w = minimal_column_width (obj);
00479 
00480   num_padded_columns = obj->drawing_area->allocation.width
00481     - ( min_col_w * obj->n_cols + 1);
00482   if (obj->n_cols - col <= num_padded_columns)
00483     return min_col_w + 1;
00484   else
00485     return min_col_w;
00486 }
00487 
00488 gint
00489 charinfo_table_row_height (UniCharInfo *obj, gint row)
00490 {
00491   gint num_padded_rows;
00492   gint min_row_h = minimal_row_height (obj);
00493 
00494   num_padded_rows = obj->drawing_area->allocation.height
00495     - ( min_row_h * obj->n_rows + 1);
00496   if (obj->n_rows - row <= num_padded_rows)
00497     return min_row_h + 1;
00498   else
00499     return min_row_h;
00500 }
00501 
00502 static void
00503 charinfo_table_redraw (UniCharInfo *obj)
00504 {
00505   gint row_offset;
00506   row_offset = ((gint) obj->first_char - (gint) obj->begin_char) /
00507     obj->n_cols;
00508   
00509 
00510 }
00511 
00512 void
00513 charinfo_table_set_current_character (UniCharInfo *obj, gunichar uc)
00514 {
00515   set_current_char (obj, uc);
00516 #if 0
00517   charinfo_table_redraw (obj);
00518 #endif
00519 }
00520 
00521 #ifdef TEST_RUN
00522 int
00523 main (int argc, char *argv[])
00524 {
00525   GtkWidget *main_window;
00526   GtkWidget *charinfo;
00527   gtk_init (&argc, &argv);
00528 
00529   main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
00530   g_signal_connect (G_OBJECT (main_window), "destroy",
00531                   G_CALLBACK (gtk_main_quit), NULL);
00532   charinfo = unicharinfo_new ();
00533   gtk_container_add (GTK_CONTAINER (main_window), charinfo);
00534   gtk_widget_show (charinfo);
00535   gtk_widget_show (main_window);
00536   
00537   
00538   gtk_main ();
00539   return 0;
00540   
00541   
00542 }
00543 
00544 #endif