00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <gtk/gtk.h>
00029 #include <gdk/gdkkeysyms.h>
00030
00031 #include "text_config.h"
00032 #include "text_model.h"
00033 #include "text_view.h"
00034
00035 using namespace text;
00036
00037 unsigned char* bmp = NULL;
00038 GdkPixbuf *pix_buf = NULL;
00039 GtkWidget *top_level_window = NULL;
00040 GdkGC* xor_gc = NULL;
00041
00042 int page_index = 0;
00043 int total_pages = 0;
00044 int cur_width = DEFAULT_SURFACE_WIDTH;
00045 int cur_height = DEFAULT_SURFACE_HEIGHT;
00046
00047
00048 std::vector<Range> result_ranges;
00049 std::vector<BoundingRectangle> result_rects;
00050
00051 void fill_pix_buf()
00052 {
00053 if (pix_buf != NULL)
00054 {
00055 g_object_unref(pix_buf);
00056 pix_buf = NULL;
00057 }
00058
00059 pix_buf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
00060 FALSE,
00061 8,
00062 cur_width,
00063 cur_height);
00064
00065 guchar *pixels = gdk_pixbuf_get_pixels(pix_buf);
00066 int rowstride = gdk_pixbuf_get_rowstride(pix_buf);
00067 int channels = gdk_pixbuf_get_n_channels(pix_buf);
00068
00069 guchar *p = NULL;
00070 for (int y=0; y<cur_height; y++)
00071 {
00072 for (int x=0; x<cur_width; x++)
00073 {
00074 p = pixels + y*rowstride + x*channels;
00075 p[0] = p[1] = p[2] = bmp[y*cur_width+x];
00076 }
00077 }
00078 }
00079
00080 static void destroy(GtkWidget *widget, gpointer data)
00081 {
00082 gtk_main_quit ();
00083 }
00084
00085 static gboolean widget_event_handler(GtkWidget *widget, GdkEvent *event, gpointer user_data)
00086 {
00087 guint key_code;
00088 GdkEventConfigure *cfg_event = NULL;
00089 GdkEventButton *button_event = NULL;
00090 TextView *view = (TextView *)user_data;
00091 const TextModel *model = view->get_model();
00092 const char *str = NULL;
00093 std::string tmp;
00094 ViewPosition view_pos;
00095 Position doc_pos;
00096 GtkWidget *dialog;
00097
00098 switch (event->type)
00099 {
00100 case GDK_KEY_PRESS:
00101 key_code = ((GdkEventKey*)event)->keyval;
00102 if (key_code == GDK_Page_Up)
00103 {
00104 if (page_index == 0)
00105 {
00106 return FALSE;
00107 }
00108 --page_index;
00109 }
00110 else if (key_code == GDK_Page_Down)
00111 {
00112 if (page_index == total_pages-1)
00113 {
00114 return FALSE;
00115 }
00116 ++page_index;
00117 }
00118 else if (key_code == GDK_equal)
00119 {
00120
00121 view->set_font_size(view->get_font_size()+1);
00122 total_pages = view->get_page_count();
00123 page_index = 0;
00124 }
00125 else if (key_code == GDK_minus)
00126 {
00127
00128 view->set_font_size(view->get_font_size()-1);
00129 total_pages = view->get_page_count();
00130 page_index = 0;
00131 }
00132
00133
00134 memset(bmp, 0xFF, cur_width * cur_height);
00135 view->render(bmp, page_index);
00136 fill_pix_buf();
00137 gdk_window_invalidate_rect(top_level_window->window, NULL, TRUE);
00138 break;
00139
00140 case GDK_CONFIGURE:
00141 cfg_event = reinterpret_cast<GdkEventConfigure *>(event);
00142 if (cfg_event->width != cur_width || cfg_event->height != cur_height)
00143 {
00144 cur_width = cfg_event->width;
00145 cur_height = cfg_event->height;
00146 view->set_display_size(cur_width, cur_height);
00147 total_pages = view->get_page_count();
00148
00149
00150 delete[] bmp;
00151 bmp = new unsigned char[cur_width * cur_height];
00152 memset(bmp, 0xFF, cur_width * cur_height);
00153 view->render(bmp, page_index = 0);
00154 fill_pix_buf();
00155 gdk_window_invalidate_rect(top_level_window->window, NULL, TRUE);
00156 }
00157 break;
00158
00159 case GDK_BUTTON_PRESS:
00160
00161 button_event = reinterpret_cast<GdkEventButton *>(event);
00162 view_pos.page_number = page_index;
00163 view_pos.x = static_cast<int>(button_event->x);
00164 view_pos.y = static_cast<int>(button_event->y);
00165 if (view->map_view_pos_to_doc_pos(view_pos, doc_pos))
00166 {
00167 str = model->get_paragraph(doc_pos.paragraph)->c_str() + doc_pos.offset;
00168 tmp = std::string(str, g_utf8_next_char(str)-str);
00169 }
00170 else
00171 {
00172 tmp = "Nothing found!";
00173 }
00174
00175 dialog = gtk_message_dialog_new(GTK_WINDOW(top_level_window),
00176 GTK_DIALOG_MODAL,
00177 GTK_MESSAGE_INFO,
00178 GTK_BUTTONS_OK,
00179 "%s", tmp.c_str());
00180 gtk_dialog_run(GTK_DIALOG(dialog));
00181 gtk_widget_destroy(dialog);
00182 break;
00183
00184 default:
00185 break;
00186 }
00187 return TRUE;
00188 }
00189
00190 static gboolean my_expose(GtkWidget *da, GdkEventExpose *event, gpointer data)
00191 {
00192 GdkGC *gc = gdk_gc_new(da->window);
00193 GdkPixbuf** pix_buf = (GdkPixbuf**)data;
00194 gdk_draw_pixbuf(da->window,
00195 gc,
00196 *pix_buf,
00197 0,
00198 0,
00199 0,
00200 0,
00201 -1,
00202 -1,
00203 GDK_RGB_DITHER_NORMAL,
00204 0,
00205 0);
00206
00207 for (unsigned int i=0; i<result_rects.size(); i++)
00208 {
00209 if (result_rects[i].page_number == page_index)
00210 {
00211 gdk_draw_rectangle(da->window,
00212 xor_gc,
00213 TRUE,
00214 result_rects[i].rect.x,
00215 result_rects[i].rect.y,
00216 result_rects[i].rect.width,
00217 result_rects[i].rect.height);
00218 }
00219 }
00220
00221 return TRUE;
00222 }
00223
00224 int main(int argc, char* argv[])
00225 {
00226 gtk_init(&argc, &argv);
00227
00228 if (argc != 2)
00229 {
00230 fprintf(stderr, "Usage: %s <file_name>.\n", argv[0]);
00231 return -1;
00232 }
00233
00234
00235 TextModel model(argv[1]);
00236 model.open();
00237 model.read_text();
00238
00239
00240
00241
00242
00243 char search_text[] = "¹ùÐ¥Ìì";
00244 Position from(0, 0);
00245 bool case_sensitive = true;
00246 bool match_whole_word = false;
00247
00248
00249 #ifdef WIN32
00250 const char* in_p = search_text;
00251 #else
00252 char* in_p = search_text;
00253 #endif
00254 size_t in_bytes_left = strlen(search_text);
00255 char out_buf[1024];
00256 char *out_p = out_buf;
00257 size_t out_bytes_left = sizeof(out_buf);
00258
00259 iconv_t conv = iconv_open("UTF-8", "GB2312");
00260 iconv(conv, &in_p, &in_bytes_left, &out_p, &out_bytes_left);
00261 iconv_close(conv);
00262
00263 *out_p = 0;
00264 model.search_all(result_ranges, out_buf, case_sensitive, match_whole_word);
00265
00266
00267 g_thread_init(NULL);
00268 TextView view(&model);
00269 view.initialize();
00270 view.paginate(NULL);
00271 total_pages = view.get_page_count();
00272
00273 for (unsigned int i=0; i<result_ranges.size(); i++)
00274 {
00275 view.get_bounding_rectangles(result_rects, result_ranges[i]);
00276 }
00277
00278 bmp = new unsigned char[cur_width * cur_height];
00279 memset(bmp, 0xFF, cur_width * cur_height);
00280 view.render(bmp, page_index);
00281 fill_pix_buf();
00282
00283
00284 top_level_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00285 gtk_widget_set_size_request(top_level_window, cur_width, cur_height);
00286
00287 gtk_widget_set_events (top_level_window,
00288 GDK_EXPOSURE_MASK | GDK_BUTTON_MOTION_MASK |
00289 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
00290 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
00291 g_signal_connect(G_OBJECT(top_level_window), "destroy", G_CALLBACK(destroy), NULL);
00292 g_signal_connect(G_OBJECT(top_level_window), "expose_event", G_CALLBACK(my_expose), &pix_buf);
00293 gtk_signal_connect(GTK_OBJECT(top_level_window), "key_press_event", GTK_SIGNAL_FUNC(widget_event_handler), &view);
00294 gtk_signal_connect(GTK_OBJECT(top_level_window), "button_press_event", GTK_SIGNAL_FUNC(widget_event_handler), &view);
00295 gtk_signal_connect(GTK_OBJECT(top_level_window), "configure_event", GTK_SIGNAL_FUNC(widget_event_handler), &view);
00296
00297
00298 gtk_widget_show_all(top_level_window);
00299
00300
00301 xor_gc = gdk_gc_new(top_level_window->window);
00302 gdk_gc_set_function(xor_gc, GDK_XOR);
00303 GdkColor color = {0xffffffff, 0xffff, 0xffff, 0xffff};
00304 gdk_gc_set_foreground(xor_gc, &color);
00305
00306 gtk_main();
00307
00308 g_object_unref(pix_buf);
00309 return 0;
00310 }
00311