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 <cstring>
00028 #include <glib.h>
00029 #include <gdk/gdkkeysyms.h>
00030 #include "notepad_rename.h"
00031 #include <libergtk/erGtkDialogJumpToPage.h>
00032
00033 #include "log.h"
00034 #include "i18n.h"
00035 #include "notepad_display_sched.h"
00036 #include "notepad_ipc.h"
00037 #include "notepad_doc.h"
00038 #include "notepad_pages.h"
00039 #include "notepad_window.h"
00040 #include "notepad_point.h"
00041 #include "notepad_thumbnail.h"
00042
00043 namespace notepad
00044 {
00045
00046 static const char ILLEGAL_FILENAME_CHARS[] = "/\\:*?<>|";
00047
00048 CNotepadWindow::CNotepadWindow()
00049 : main_window(0)
00050 , source(this)
00051 , notepad_doc()
00052 , notepad_pages()
00053 , gctx()
00054 , current_image(0)
00055 , erscribble_mode(TRUE)
00056 , erscribble_status(-1)
00057 , erase_status(-1)
00058 , current_page(1)
00059 , invert_pageturn(FALSE)
00060 , skip_expose_events(FALSE)
00061 , doublepagefliptimout(0)
00062 {
00063
00064 }
00065
00066 bool CNotepadWindow::init(bool docreate, const gchar* filename)
00067 {
00068
00069 np_result res = NP_OK;
00070 if (docreate)
00071 {
00072 res = notepad_doc.create(filename);
00073 }
00074 else
00075 {
00076 res = notepad_doc.open(filename);
00077 }
00078
00079 if (res != NP_OK)
00080 {
00081 menu_block(TRUE);
00082 GtkWidget* openfaildialog = gtk_message_dialog_new(
00083 GTK_WINDOW(main_window),
00084 GTK_DIALOG_MODAL,
00085 GTK_MESSAGE_WARNING,
00086 GTK_BUTTONS_OK,
00087 (docreate) ?
00088 _("A new note cannot be created at this time. \n"
00089 "It is possible that the memory card is full. "
00090 "Consider deleting some items and then try again.")
00091 :
00092 _("The note could not be opened. \n"
00093 "It is possible that the file has been corrupted."));
00094
00095 gtk_dialog_run(GTK_DIALOG(openfaildialog));
00096 menu_block(FALSE);
00097 gtk_widget_destroy(openfaildialog);
00098
00099 return false;
00100 }
00101
00102
00103 main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00104 connect_event_handlers(main_window);
00105 g_signal_connect(main_window, "destroy", G_CALLBACK(gtk_widget_destroyed), &main_window);
00106 gtk_window_maximize(GTK_WINDOW(main_window));
00107
00108
00109 if ( notepad_doc.get_num_pages() < 1 )
00110 {
00111 notepad_doc.insert_page(current_page);
00112 }
00113 else
00114 {
00115 int num = notepad_doc.get_last_read();
00116 if (num > 0 )
00117 {
00118 current_page = num;
00119 }
00120 }
00121
00122
00123 gtk_widget_realize(main_window);
00124 GdkVisual* visual = gdk_drawable_get_visual(GDK_DRAWABLE(main_window->window));
00125 notepad_pages.init(¬epad_doc, &gctx, current_page, visual);
00126
00127
00128 if (gctx.gc == 0)
00129 {
00130 gctx.gc = gdk_gc_new(GDK_DRAWABLE(main_window->window));
00131 }
00132
00133
00134 return true;
00135 }
00136
00137 CNotepadWindow::~CNotepadWindow()
00138 {
00139 notepad_doc.set_last_read(current_page);
00140 notepad_doc.close();
00141 disconnect_event_handlers(main_window);
00142 notepad_pages.stop();
00143
00144 if (main_window)
00145 {
00146 gtk_widget_destroy(main_window);
00147 main_window = 0;
00148 }
00149 if (gctx.gc != 0)
00150 {
00151 g_object_unref(G_OBJECT(gctx.gc));
00152 gctx.gc = 0;
00153 }
00154 }
00155
00156 void CNotepadWindow::quit()
00157 {
00158 LOGPRINTF("entry");
00159
00160 CThumbnail saveThumbnail(*notepad_doc.getFileStore(), notepad_pages, gctx.margin);
00161
00162 notepad_pages.stop();
00163 gtk_main_quit();
00164 }
00165
00166 GtkWidget* CNotepadWindow::getWindow()
00167 {
00168 return main_window;
00169 }
00170
00171 gchar* CNotepadWindow::getLabel()
00172 {
00173 CFileStore* store = notepad_doc.getFileStore();
00174 return store->getFileNameFilePartNoExt();
00175 }
00176
00177 const gchar* CNotepadWindow::getFilename()
00178 {
00179 CFileStore* store = notepad_doc.getFileStore();
00180 return store->getFilename();
00181 }
00182
00183
00184 void CNotepadWindow::show(bool show)
00185 {
00186 LOGPRINTF("entry");
00187 if (show)
00188 gtk_widget_show(main_window);
00189 else
00190 gtk_widget_hide(main_window);
00191 LOGPRINTF("exit");
00192 }
00193
00194 void CNotepadWindow::connect_event_handlers(GtkWidget *widget)
00195 {
00196
00197 source.connect_event_handlers(widget);
00198 source.set_event_handler(EventSource::EVENT_EXPOSE,
00199 &CNotepadWindow::on_expose);
00200 source.set_event_handler(EventSource::EVENT_VISIBILITY_NOTIFY,
00201 &CNotepadWindow::on_visibility_notify);
00202 source.set_event_handler(EventSource::EVENT_CONFIG,
00203 &CNotepadWindow::on_configure);
00204 source.set_event_handler(EventSource::EVENT_BUTTON_PRESS,
00205 &CNotepadWindow::on_button_press);
00206 source.set_event_handler(EventSource::EVENT_BUTTON_RELEASE,
00207 &CNotepadWindow::on_button_release);
00208 source.set_event_handler(EventSource::EVENT_MOTION_NOTIFY,
00209 &CNotepadWindow::on_motion_notify);
00210 source.set_event_handler(EventSource::EVENT_KEY_PRESS,
00211 &CNotepadWindow::on_key_press);
00212 source.set_event_handler(EventSource::EVENT_KEY_RELEASE,
00213 &CNotepadWindow::on_key_release);
00214 source.set_event_handler(EventSource::EVENT_DELETE,
00215 &CNotepadWindow::on_delete);
00216 }
00217
00218 void CNotepadWindow::on_configure(GdkEvent* event)
00219 {
00220 LOGPRINTF("entry");
00221
00222
00223 GdkEventConfigure *cfg_event = reinterpret_cast<GdkEventConfigure *>(event);
00224
00225
00226
00227 if (cfg_event->send_event == TRUE)
00228 {
00229 LOGPRINTF("exit, skipped, send_event == true");
00230 return;
00231 }
00232
00233
00234 if ( (gctx.width == cfg_event->width )
00235 && (gctx.height == cfg_event->height) )
00236 {
00237 LOGPRINTF("exit, size not changed, skip");
00238 return;
00239 }
00240
00241
00242 set_rotation( ipc_get_rotation() );
00243
00244 LOGPRINTF("exit");
00245 }
00246
00247 void CNotepadWindow::on_expose(GdkEvent* event)
00248 {
00249 LOGPRINTF("entry");
00250 static bool blockedstate = false;
00251
00252
00253 if (skip_expose_events)
00254 {
00255 blockedstate = true;
00256 LOGPRINTF("exit, skipped");
00257 return;
00258 }
00259 if (blockedstate)
00260 {
00261 blockedstate = false;
00262 }
00263 if (gctx.gc != 0)
00264 {
00265 update();
00266 }
00267
00268 LOGPRINTF("exit");
00269 }
00270
00271 void CNotepadWindow::on_visibility_notify(GdkEvent* event)
00272 {
00273
00274
00275
00276
00277 GdkEventVisibility* v_event = reinterpret_cast<GdkEventVisibility *>(event);
00278 LOGPRINTF("%d", v_event->state);
00279 if (!skip_expose_events)
00280 {
00281 if (v_event->state == GDK_VISIBILITY_FULLY_OBSCURED)
00282 {
00283 skip_expose_events = true;
00284 LOGPRINTF("GDK_VISIBILITY_FULLY_OBSCURED, skip_expose_events");
00285 }
00286 else
00287 {
00288
00289
00290
00291
00292 LOGPRINTF("quick refresh screen");
00293 draw_image_to_window();
00294 }
00295 }
00296 else
00297 {
00298 if (v_event->state == GDK_VISIBILITY_UNOBSCURED)
00299 {
00300 skip_expose_events = false;
00301 LOGPRINTF("GDK_VISIBILITY_UNOBSCURED, pass expose_events and invalidate whole window");
00302
00303 GdkRectangle rect = {0,0, gctx.width, gctx.height};
00304 gdk_window_invalidate_rect(main_window->window, &rect, FALSE);
00305 }
00306 }
00307 }
00308
00309 void CNotepadWindow::set_rotation(np_rotation rotation)
00310 {
00311
00312 LOGPRINTF("entry");
00313
00314 if (gctx.width != 0 && gctx.height != 0)
00315 {
00316
00317 (void) save();
00318 }
00319
00320 if (rotation != gctx.rotation)
00321 {
00322 LOGPRINTF("change rotation, erase page cache");
00323 notepad_pages.mark_all_dirty();
00324 }
00325
00326
00327 int width, height;
00328 gtk_window_get_size(GTK_WINDOW(main_window), &width, &height);
00329
00330
00331 int root_width, root_height;
00332 gdk_window_get_geometry(gdk_get_default_root_window(), NULL, NULL, &root_width, &root_height, NULL);
00333
00334 int posx = 0, posy = 0;
00335 gdk_window_get_position(main_window->window, &posx, &posy);
00336
00337 gctx.rotation = rotation;
00338 gctx.width = width;
00339 gctx.height = height;
00340
00341 int my_border = root_height - height;
00342 gctx.margin = my_border;
00343
00344 CNPoint::setRotation(rotation);
00345 CNPoint::setScreen(root_width, root_height);
00346 CNPoint::setClipBorder(my_border);
00347
00348 LOGPRINTF("gdk_window_get_position: x = %d, y = %d\n", posx, posy);
00349 LOGPRINTF("rotation %d", gctx.rotation);
00350 LOGPRINTF("root_widht %d, root_height %d", root_width, root_height);
00351 LOGPRINTF("widht %d, height %d", width, height);
00352 LOGPRINTF("border %d", my_border);
00353
00354
00355 LOGPRINTF("exit");
00356 }
00357
00358 void CNotepadWindow::disconnect_event_handlers(GtkWidget *widget)
00359 {
00360 source.disconnect_event_handlers(widget);
00361 }
00362
00363 void CNotepadWindow::on_button_press(GdkEvent* event)
00364 {
00365
00366 GdkEventButton * button_event = reinterpret_cast<GdkEventButton*>(event);
00367 int win_x = static_cast<int>(button_event->x);
00368 int win_y = static_cast<int>(button_event->y);
00369
00370
00371 switch (button_event->button)
00372 {
00373 case 1:
00374 {
00375 CNPoint cpos(win_x, win_y);
00376 LOGPRINTF("cpos %d, %d", win_x , win_y);
00377 LOGPRINTF(">>cpos %d, %d", cpos.storageView().x, cpos.storageView().y);
00378
00379 if (erscribble_mode)
00380 {
00381 if (erscribble_status < 0)
00382 {
00383 erscribble_status = 0;
00384 scribble(cpos, erscribble_status);
00385 }
00386 }
00387 else
00388 {
00389 if (erase_status < 0)
00390 {
00391 erase_status = 0;
00392 erase(cpos, erase_status);
00393 }
00394 }
00395 }
00396 break;
00397 default:
00398 break;
00399 }
00400 }
00401
00402 void CNotepadWindow::on_button_release(GdkEvent* event)
00403 {
00404
00405 GdkEventButton * button_event = reinterpret_cast<GdkEventButton *>(event);
00406 int win_x = static_cast<int>(button_event->x);
00407 int win_y = static_cast<int>(button_event->y);
00408
00409
00410 switch (button_event->button)
00411 {
00412 case 1:
00413 {
00414 CNPoint cpos(win_x, win_y);
00415
00416 if (erscribble_mode)
00417 {
00418 if (erscribble_status >= 0)
00419 {
00420 erscribble_status = 2;
00421 scribble(cpos, erscribble_status);
00422
00423
00424 erscribble_status = -1;
00425 }
00426 }
00427 else
00428 {
00429 if (erase_status >= 0)
00430 {
00431 erase_status = 2;
00432 erase(cpos, erase_status);
00433
00434
00435 erase_status = -1;
00436 }
00437 }
00438 }
00439 break;
00440 default:
00441 break;
00442 }
00443 }
00444
00445 void CNotepadWindow::on_motion_notify(GdkEvent* event)
00446 {
00447 GdkEventButton * button_event = reinterpret_cast<GdkEventButton *>(event);
00448 int win_x = static_cast<int>(button_event->x);
00449 int win_y = static_cast<int>(button_event->y);
00450
00451 CNPoint cpos(win_x, win_y);
00452
00453 if (erscribble_mode)
00454 {
00455 if (erscribble_status == 0)
00456 {
00457 erscribble_status = 1;
00458 }
00459
00460 if (erscribble_status == 1)
00461 {
00462 scribble(cpos, erscribble_status);
00463 }
00464 }
00465 else
00466 {
00467 if (erase_status == 0)
00468 {
00469 erase_status = 1;
00470 }
00471
00472 if (erase_status == 1)
00473 {
00474 erase(cpos, erase_status);
00475 }
00476 }
00477 }
00478
00479 void CNotepadWindow::on_key_press(GdkEvent* event)
00480 {
00481 }
00482
00483 void CNotepadWindow::on_key_release(GdkEvent* event)
00484 {
00485 guint key_code = ((GdkEventKey*)event)->keyval;
00486
00487 switch(key_code)
00488 {
00489 case GDK_Page_Up:
00490 case GDK_Home:
00491 if (invert_pageturn)
00492 goto_relative_page(5);
00493 else
00494 goto_relative_page(-5);
00495 break;
00496 case GDK_Page_Down:
00497 case GDK_End:
00498 if (invert_pageturn)
00499 goto_relative_page(-5);
00500 else
00501 goto_relative_page(5);
00502 break;
00503 case GDK_Up:
00504 if (invert_pageturn)
00505 pageflip_forward();
00506 else
00507 pageflip_back();
00508 break;
00509 case GDK_Down:
00510 if (invert_pageturn)
00511 pageflip_back();
00512 else
00513 pageflip_forward();
00514 break;
00515 case GDK_Left:
00516 pageflip_back();
00517 break;
00518 case GDK_Right:
00519 pageflip_forward();
00520 break;
00521 case GDK_Return:
00522 default:
00523 break;
00524 }
00525 }
00526
00527 void CNotepadWindow::on_delete(GdkEvent* event)
00528 {
00529 quit();
00530 }
00531
00532 void CNotepadWindow::scribble(CNPoint& pos, int status)
00533 {
00534 switch(status)
00535 {
00536 case 0:
00537 notepad_doc.on_scribble_begin(current_page, gctx, current_image, pos );
00538 break;
00539 case 1:
00540 notepad_doc.on_scribble_move(current_page, gctx, current_image, pos );
00541 break;
00542 case 2:
00543 notepad_doc.on_scribble_end(current_page, gctx, current_image, pos );
00544 break;
00545 default:
00546 break;
00547 }
00548 }
00549
00550 void CNotepadWindow::erase(CNPoint& pos, int status)
00551 {
00552 switch(status)
00553 {
00554 case 0:
00555 notepad_doc.on_erase_begin(current_page, gctx, current_image, pos);
00556 break;
00557 case 1:
00558 notepad_doc.on_erase_move(current_page, gctx, current_image, pos);
00559 break;
00560 case 2:
00561 notepad_doc.on_erase_end(current_page, gctx, current_image, pos);
00562 notepad_pages.mark_dirty(current_page);
00563 break;
00564 default:
00565 break;
00566 }
00567 }
00568
00569 void CNotepadWindow::draw_page_margin()
00570 {
00571
00572
00573 LOGPRINTF("entry");
00574
00575 g_assert(main_window != 0);
00576 g_assert(main_window->window != 0);
00577
00578
00579 GdkGC* border_gc = gdk_gc_new(main_window->window);
00580 if (border_gc != 0)
00581 {
00582 gdk_gc_set_line_attributes(border_gc, 3, GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
00583
00584 GdkColor darkgrey = {0xAAAAAAAA, 0xAAAA, 0xAAAA, 0xAAAA};
00585
00586
00587 gdk_gc_set_rgb_fg_color(border_gc, &darkgrey);
00588
00589 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00590 gdk_draw_rectangle(main_window->window, border_gc, FALSE, gctx.margin-1, gctx.margin-1, (gctx.width - gctx.margin + 1), (gctx.height - gctx.margin + 1));
00591 #endif
00592 #if MACHINE_IS_DR800S || MACHINE_IS_DR800SG || MACHINE_IS_DR800SW
00593 gdk_draw_rectangle(main_window->window, border_gc, FALSE, gctx.margin-1, gctx.margin-1, (gctx.width - 2*gctx.margin + 2), (gctx.height - gctx.margin + 1));
00594 #endif
00595
00596 g_object_unref(border_gc);
00597 }
00598 LOGPRINTF("exit");
00599 }
00600
00601 void CNotepadWindow::draw_image_to_window()
00602 {
00603
00604 if (current_image && main_window && main_window->window)
00605 {
00606 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00607 gdk_draw_image(GDK_DRAWABLE(main_window->window), gctx.gc, current_image,
00608 gctx.margin, gctx.margin,
00609 gctx.margin, gctx.margin,
00610 (gctx.width - gctx.margin), (gctx.height - gctx.margin));
00611 #endif
00612 #if MACHINE_IS_DR800S || MACHINE_IS_DR800SG || MACHINE_IS_DR800SW
00613 gdk_draw_image(GDK_DRAWABLE(main_window->window), gctx.gc, current_image,
00614 gctx.margin, gctx.margin,
00615 gctx.margin, gctx.margin,
00616 (gctx.width - 2*gctx.margin), (gctx.height - gctx.margin));
00617 #endif
00618 }
00619 }
00620
00621 void CNotepadWindow::update(bool full)
00622 {
00623 LOGPRINTF("entry %d", current_page);
00624
00625 g_assert(gctx.gc != 0);
00626
00627
00628 current_image = notepad_pages.get_page(current_page);
00629
00630
00631 draw_image_to_window();
00632
00633
00634 draw_page_margin();
00635
00636
00637 if (full)
00638 {
00639 notepad_stop_display_update();
00640 notepad_on_idle_display_yield(DM_HINT_FULL);
00641 }
00642 else
00643 {
00644 notepad_start_display_update();
00645 }
00646
00647 LOGPRINTF("exit");
00648 }
00649
00650 void CNotepadWindow::goto_relative_page(gint delta)
00651 {
00652 gint pageno = current_page + delta;
00653 LOGPRINTF("current_page %d delta %d pageno %d", current_page, delta, pageno);
00654 goto_page(pageno);
00655 }
00656
00657 void CNotepadWindow::on_jump_to_page_dialog_response(GtkDialog* dialog, gint pageno, gpointer data)
00658 {
00659 LOGPRINTF("entry %d", pageno);
00660 g_assert(data != 0);
00661
00662 if (pageno >= 0)
00663 {
00664 CNotepadWindow* instance = static_cast<CNotepadWindow*>(data);
00665 instance->goto_page(pageno);
00666 }
00667
00668 menu_block(FALSE);
00669 gtk_widget_destroy(GTK_WIDGET(dialog));
00670
00671 LOGPRINTF("exit");
00672 }
00673
00674 void CNotepadWindow::goto_page()
00675 {
00676 LOGPRINTF("entry");
00677 (void) save();
00678
00679 menu_block(TRUE);
00680 GtkWidget* jumptopagedialog = ergtk_jump_to_page_dialog_new();
00681 g_signal_connect(jumptopagedialog,
00682 "response",
00683 G_CALLBACK (CNotepadWindow::on_jump_to_page_dialog_response),
00684 static_cast<gpointer>(this) );
00685 gtk_widget_show_all(jumptopagedialog);
00686 LOGPRINTF("exit");
00687 }
00688
00689 void CNotepadWindow::goto_page(gint pageno)
00690 {
00691 LOGPRINTF("entry %d", pageno);
00692 (void) save();
00693
00694 current_page = pageno;
00695 if (current_page > notepad_doc.get_num_pages())
00696 {
00697 current_page = notepad_doc.get_num_pages();
00698 }
00699 if (current_page < 1)
00700 {
00701 current_page = 1;
00702 }
00703 update_page_counter();
00704 update();
00705
00706 LOGPRINTF("exit");
00707 }
00708
00709
00710
00711 void CNotepadWindow::pageflip_or_create()
00712 {
00713 LOGPRINTF("entry %d", pageflipto);
00714
00715
00716 save();
00717
00718 current_page = pageflipto;
00719
00720 if (current_page < 1)
00721 {
00722 current_page = 1;
00723 }
00724
00725 if (current_page > notepad_doc.get_num_pages())
00726 {
00727 current_page = notepad_doc.get_num_pages() + 1;
00728 notepad_doc.add_page(current_page);
00729 notepad_pages.insert_page(current_page);
00730 LOGPRINTF("increased: %d", current_page);
00731 }
00732
00733 LOGPRINTF("to %d", current_page);
00734 update_page_counter();
00735 update();
00736
00737 LOGPRINTF("exit");
00738 doublepagefliptimout = 0;
00739 }
00740
00741 gboolean static_pageflip(gpointer data)
00742 {
00743 CNotepadWindow* instance = (CNotepadWindow*) data;
00744 instance->pageflip_or_create();
00745 return FALSE;
00746 }
00747
00748
00749 void CNotepadWindow::pageflip_back()
00750 {
00751 LOGPRINTF("entry");
00752
00753 if (doublepagefliptimout)
00754 {
00755 GSource* gsrc = g_main_context_find_source_by_id(NULL, doublepagefliptimout);
00756 g_source_destroy(gsrc);
00757 --pageflipto;
00758 }
00759 else
00760 {
00761 pageflipto = current_page - 1;
00762 }
00763
00764
00765 doublepagefliptimout = g_timeout_add(500, static_pageflip, this);
00766
00767 LOGPRINTF("exit");
00768 }
00769
00770 void CNotepadWindow::pageflip_forward()
00771 {
00772 LOGPRINTF("entry");
00773
00774 if (doublepagefliptimout)
00775 {
00776 GSource* gsrc = g_main_context_find_source_by_id(NULL, doublepagefliptimout);
00777 g_source_destroy(gsrc);
00778 ++pageflipto;
00779 }
00780 else
00781 {
00782 pageflipto = current_page + 1;
00783 }
00784
00785 doublepagefliptimout = g_timeout_add(500, static_pageflip, this);
00786
00787 LOGPRINTF("exit");
00788 }
00789
00790 void CNotepadWindow::insert_page()
00791 {
00792 LOGPRINTF("entry");
00793 (void) save();
00794
00795 notepad_doc.insert_page(current_page);
00796
00797 notepad_pages.insert_page(current_page);
00798
00799 update_page_counter();
00800 update();
00801
00802 LOGPRINTF("exit");
00803 }
00804
00805
00806 void CNotepadWindow::on_sureclear_dialog_response(GtkDialog* dialog, gint response, gpointer data)
00807 {
00808 LOGPRINTF("entry");
00809 g_assert(data != 0);
00810 CNotepadWindow* instance = static_cast<CNotepadWindow*>(data);
00811
00812 if (response == GTK_RESPONSE_YES)
00813 {
00814 instance->notepad_doc.clear_page(instance->current_page);
00815 instance->notepad_pages.clear_page(instance->current_page);
00816 instance->update();
00817 (void) instance->save();
00818 }
00819
00820 menu_block(FALSE);
00821 gtk_widget_destroy(GTK_WIDGET(dialog));
00822
00823 LOGPRINTF("exit");
00824 }
00825
00826 void CNotepadWindow::on_suredelete_dialog_response(GtkDialog* dialog, gint response, gpointer data)
00827 {
00828 LOGPRINTF("entry");
00829 g_assert(data != 0);
00830 CNotepadWindow* instance = static_cast<CNotepadWindow*>(data);
00831
00832 if (response == GTK_RESPONSE_YES)
00833 {
00834 instance->delete_current_page_impl();
00835 }
00836
00837 menu_block(FALSE);
00838 gtk_widget_destroy(GTK_WIDGET(dialog));
00839
00840 LOGPRINTF("exit");
00841 }
00842
00843
00844 void CNotepadWindow::clear_current_page()
00845 {
00846 LOGPRINTF("entry");
00847 GtkWidget* surecleardialog = gtk_message_dialog_new(
00848 GTK_WINDOW(main_window),
00849 GTK_DIALOG_MODAL,
00850 GTK_MESSAGE_QUESTION,
00851 GTK_BUTTONS_YES_NO,
00852 _("Are you sure you want to clear the writing from this page?") );
00853
00854 g_signal_connect(surecleardialog,
00855 "response",
00856 G_CALLBACK (CNotepadWindow::on_sureclear_dialog_response),
00857 static_cast<gpointer>(this) );
00858 gtk_widget_show_all(surecleardialog);
00859
00860 LOGPRINTF("exit");
00861 }
00862
00863 void CNotepadWindow::delete_current_page()
00864 {
00865 LOGPRINTF("entry");
00866 GtkWidget* suredeletedialog = gtk_message_dialog_new(
00867 GTK_WINDOW(main_window),
00868 GTK_DIALOG_MODAL,
00869 GTK_MESSAGE_QUESTION,
00870 GTK_BUTTONS_YES_NO,
00871 _("Are you sure you want to delete this page from the notepad?") );
00872
00873 g_signal_connect(suredeletedialog,
00874 "response",
00875 G_CALLBACK (CNotepadWindow::on_suredelete_dialog_response),
00876 static_cast<gpointer>(this) );
00877 gtk_widget_show_all(suredeletedialog);
00878
00879 LOGPRINTF("exit");
00880 }
00881
00882 void CNotepadWindow::delete_current_page_impl()
00883 {
00884 LOGPRINTF("entry");
00885
00886 if (notepad_doc.get_num_pages() <= 1)
00887 {
00888 LOGPRINTF("current_pages %d", current_page);
00889 current_page = 1;
00890 notepad_doc.clear_page(1);
00891 notepad_pages.clear_page(1);
00892 }
00893 else
00894 {
00895 notepad_doc.delete_page(current_page);
00896
00897
00898 notepad_pages.delete_page(current_page);
00899 LOGPRINTF("current_pages %d", current_page);
00900
00901 if (current_page > notepad_doc.get_num_pages())
00902 {
00903 LOGPRINTF("current_pages %d", current_page);
00904 current_page = notepad_doc.get_num_pages();
00905 }
00906 }
00907 update_page_counter();
00908 update();
00909
00910 LOGPRINTF("exit");
00911 }
00912
00913 void CNotepadWindow::update_page_counter()
00914 {
00915 LOGPRINTF("entry");
00916 ipc_menu_set_pagecounter(current_page, notepad_doc.get_num_pages() );
00917 }
00918
00919 void CNotepadWindow::on_failure_dialog_response(GtkDialog* dialog, gint response, gpointer data)
00920 {
00921 LOGPRINTF("entry");
00922 g_assert(data != 0);
00923 CNotepadWindow* instance = static_cast<CNotepadWindow*>(data);
00924 instance->quit();
00925 }
00926
00927 gboolean CNotepadWindow::save(bool update_last_read)
00928 {
00929 if (gctx.width == 0 || gctx.height == 0)
00930 {
00931 WARNPRINTF("try to save in uninitialized state");
00932 return FALSE;
00933 }
00934
00935 LOGPRINTF("entry");
00936
00937
00938 if (current_page == 1 && notepad_doc.get_page_dirty())
00939 {
00940
00941
00942 CThumbnail saveThumbnail(*notepad_doc.getFileStore(), notepad_pages, gctx.margin);
00943 }
00944
00945 np_result res = notepad_doc.save_page(current_page, update_last_read);
00946
00947 if (res != NP_OK)
00948 {
00949 GtkWidget* save_failuredialog = gtk_message_dialog_new(
00950 GTK_WINDOW(main_window),
00951 GTK_DIALOG_MODAL,
00952 GTK_MESSAGE_WARNING,
00953 GTK_BUTTONS_OK,
00954
00955 _("The changes to the page could not be saved. \n"
00956 "Notes must close because of this problem."));
00957
00958
00959 g_signal_connect(save_failuredialog,
00960 "response",
00961 G_CALLBACK (CNotepadWindow::on_failure_dialog_response),
00962 static_cast<gpointer>(this) );
00963 gtk_widget_show_all(save_failuredialog);
00964 }
00965
00966 return (res == NP_OK);
00967 }
00968
00969
00970
00971 static gboolean check_filename_valid(const char* filename)
00972 {
00973 gboolean name_valid = TRUE;
00974 glong len = strlen(filename);
00975
00976 if (len == 0)
00977 {
00978
00979 WARNPRINTF("rename to empty filename");
00980 name_valid = FALSE;
00981 }
00982 else if (len > 200)
00983 {
00984
00985 WARNPRINTF("filename to long");
00986 name_valid = FALSE;
00987 }
00988 else if (filename[0] == '.')
00989 {
00990
00991 WARNPRINTF("hiddenfile not allowed");
00992 name_valid = FALSE;
00993 }
00994 else if (g_unichar_isspace(filename[0]))
00995 {
00996
00997 WARNPRINTF("no spaces allowed on first character");
00998 name_valid = FALSE;
00999 }
01000 else
01001 {
01002
01003
01004 int n_illegal = strlen(ILLEGAL_FILENAME_CHARS);
01005 for (int i = 0; ((name_valid) && (i < n_illegal)); i++)
01006 {
01007 if ( NULL != strchr(filename, ILLEGAL_FILENAME_CHARS[i]) )
01008 {
01009 LOGPRINTF("illegal character %c found", ILLEGAL_FILENAME_CHARS[i]);
01010 name_valid = FALSE;
01011 }
01012 }
01013 }
01014 return name_valid;
01015 }
01016
01017 void CNotepadWindow::on_rename_dialog_response(GtkDialog* dialog, gint response, gpointer data)
01018 {
01019 LOGPRINTF("entry");
01020 g_assert(data != 0);
01021 CNotepadWindow* instance = static_cast<CNotepadWindow*>(data);
01022
01023 if (response == GTK_RESPONSE_ACCEPT)
01024 {
01025 np_result rename_result = NP_OK;
01026
01027 const gchar* newfilename = rename_get_text();
01028
01029 gchar* my_file = instance->notepad_doc.get_filename_without_dir_and_ext();
01030 if (0 == g_strcmp0(newfilename, my_file))
01031 {
01032 LOGPRINTF("rename to same file");
01033
01034 rename_result = NP_OK;
01035 }
01036 else if ( ! check_filename_valid(newfilename) )
01037 {
01038 LOGPRINTF("invalid filename entered %s", newfilename);
01039 rename_result = NP_NO_FILENAME;
01040 }
01041 else
01042 {
01043 rename_result = instance->notepad_doc.rename(newfilename);
01044 }
01045 g_free(my_file); my_file = 0;
01046
01047
01048 switch (rename_result)
01049 {
01050 case NP_OK:
01051 break;
01052 case NP_NO_FILENAME:
01053 {
01054 notepad_stop_display_update();
01055 GtkWidget* infodialog = gtk_message_dialog_new(
01056 GTK_WINDOW(instance->main_window),
01057 GTK_DIALOG_MODAL,
01058 GTK_MESSAGE_WARNING,
01059 GTK_BUTTONS_OK,
01060 _("The file name is not valid. \n"
01061 "Remember that / \\ |: * ? < or > cannot be used in the name and it cannot begin with a space or period.") );
01062
01063 notepad_on_timeout_display_yield(400, DM_HINT_FULL);
01064 gtk_dialog_run(GTK_DIALOG(infodialog));
01065 gtk_widget_destroy(infodialog);
01066 rename_set_focus();
01067
01068 return;
01069 }
01070 break;
01071 case NP_FILE_EXISTS:
01072 {
01073 notepad_stop_display_update();
01074 GtkWidget* infodialog = gtk_message_dialog_new(
01075 GTK_WINDOW(instance->main_window),
01076 GTK_DIALOG_MODAL,
01077 GTK_MESSAGE_WARNING,
01078 GTK_BUTTONS_OK,
01079 _("This name has already been used for another note. \n"
01080 "Please choose a different name.") );
01081
01082 notepad_on_timeout_display_yield(400, DM_HINT_FULL);
01083 gtk_dialog_run(GTK_DIALOG(infodialog));
01084 gtk_widget_destroy(infodialog);
01085
01086 rename_set_focus();
01087 return;
01088 }
01089 break;
01090 default:
01091 {
01092 notepad_stop_display_update();
01093 GtkWidget* infodialog = gtk_message_dialog_new(
01094 GTK_WINDOW(instance->main_window),
01095 GTK_DIALOG_MODAL,
01096 GTK_MESSAGE_WARNING,
01097 GTK_BUTTONS_OK,
01098 _("The note could not be renamed for an unexpected reason. \n"
01099 "Please try again or contact customer support if you continue to experience this problem.") );
01100
01101 notepad_on_timeout_display_yield(400, DM_HINT_FULL);
01102 gtk_dialog_run(GTK_DIALOG(infodialog));
01103 gtk_widget_destroy(infodialog);
01104 }
01105 break;
01106 }
01107 }
01108 menu_block(FALSE);
01109 gtk_widget_destroy(GTK_WIDGET(dialog));
01110
01111 LOGPRINTF("exit");
01112 }
01113
01114 gboolean CNotepadWindow::rename()
01115 {
01116 LOGPRINTF("entry");
01117
01118 menu_block(TRUE);
01119 (void) save();
01120 gchar* my_file = notepad_doc.get_filename_without_dir_and_ext();
01121 GtkWidget* renamedialog = rename_dialog_create(main_window, my_file);
01122 g_signal_connect(renamedialog,
01123 "response",
01124 G_CALLBACK (CNotepadWindow::on_rename_dialog_response),
01125 static_cast<gpointer>(this) );
01126
01127 g_free(my_file);
01128 my_file = 0;
01129 LOGPRINTF("exit");
01130 return FALSE;
01131 }
01132
01133 void CNotepadWindow::set_scribble_mode(gboolean scribble_mode)
01134 {
01135 erscribble_mode = scribble_mode;
01136 update(false);
01137 }
01138
01139 gboolean CNotepadWindow::get_scribble_mode()
01140 {
01141 return erscribble_mode;
01142 }
01143
01144 void CNotepadWindow::set_pageturn_inverted(gboolean is_inverted)
01145 {
01146 invert_pageturn = is_inverted;
01147 }
01148 }