/* * IupScintilla component * * Description : A source code editing component, * derived from Scintilla (http://www.scintilla.org/) */ #include #include #include #include #include "Scintilla.h" #include "SciLexer.h" #include #include "ScintillaWidget.h" #include "iup.h" #include "iup_scintilla.h" #include "iupcbs.h" #include "iup_key.h" #include "iup_class.h" #include "iup_object.h" #include "iup_attrib.h" #include "iup_str.h" #include "iup_drv.h" #include "iup_drvfont.h" #include "iup_register.h" #include "iup_layout.h" #include "iup_assert.h" #include "iup_array.h" #include "iupgtk_drv.h" #include "iupsci.h" void iupdrvScintillaRefreshCaret(Ihandle* ih) { (void)ih; } int iupdrvScintillaGetBorder(void) { int border_size = 2 * 5; return border_size; } void iupdrvScintillaOpen(void) { } sptr_t IupScintillaSendMessage(Ihandle* ih, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return scintilla_send_message(SCINTILLA(ih->handle), iMessage, wParam, lParam); } static void gtkScintillaNotify(GtkWidget *w, gint wp, gpointer lp, Ihandle *ih) { SCNotification *pMsg =(SCNotification*)lp; iupScintillaNotify(ih, pMsg); (void)w; (void)wp; } static gboolean gtkScintillaKeyReleaseEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih) { iupScintillaCallCaretCb(ih); (void)widget; (void)evt; return FALSE; } static gboolean gtkScintillaButtonEvent(GtkWidget *widget, GdkEventButton *evt, Ihandle *ih) { iupScintillaCallCaretCb(ih); return iupgtkButtonEvent(widget, evt, ih); } static void gtkScintillaSetupFormat(struct Sci_RangeToFormat *frPrint, GtkPrintContext *context, Ihandle* ih) { int margin_left, margin_top, margin_right, margin_bottom, margin_units, page_width, page_height; double dpi; cairo_t *cr = gtk_print_context_get_cairo_context(context); frPrint->hdc = cr; frPrint->hdcTarget = cr; page_width = (int)gtk_print_context_get_width(context); page_height = (int)gtk_print_context_get_height(context); dpi = gtk_print_context_get_dpi_y(context); margin_units = iupSciGetPrintMarginUnits(ih); margin_left = iupSciGetPrintMargin(ih, "PRINTMARGINLEFT", margin_units, dpi); margin_top = iupSciGetPrintMargin(ih, "PRINTMARGINTOP", margin_units, dpi); margin_right = iupSciGetPrintMargin(ih, "PRINTMARGINRIGHT", margin_units, dpi); margin_bottom = iupSciGetPrintMargin(ih, "PRINTMARGINBOTTOM", margin_units, dpi); frPrint->rc.left = margin_left; frPrint->rc.top = margin_top; frPrint->rc.right = page_width - margin_right; frPrint->rc.bottom = page_height - margin_bottom; frPrint->rcPage.left = 0; frPrint->rcPage.top = 0; frPrint->rcPage.right = page_width; frPrint->rcPage.bottom = page_height; } static void gtkScintillaBeginPrint(GtkPrintOperation *operation, GtkPrintContext *context, Ihandle* ih) { int lengthPrinted, lengthDoc, p, lengthDocMax; struct Sci_RangeToFormat frPrint; Iarray* page_starts_array = (Iarray*)iupAttribGet(ih, "_IUP_PAGE_ARRAY"); int* page_starts; int startPos = 0, endPos = 0; IupGetIntInt(ih, "SELECTIONPOS", &startPos, &endPos); gtkScintillaSetupFormat(&frPrint, context, ih); lengthDoc = (int)IupScintillaSendMessage(ih, SCI_GETLENGTH, 0, 0); lengthPrinted = 0; lengthDocMax = lengthDoc; #if GTK_CHECK_VERSION(2, 18, 0) if (startPos != endPos && gtk_print_operation_get_has_selection(operation)) { if (startPos > endPos) { lengthPrinted = endPos; lengthDoc = startPos; } else { lengthPrinted = startPos; lengthDoc = endPos; } if (lengthPrinted < 0) lengthPrinted = 0; if (lengthDoc > lengthDocMax) lengthDoc = lengthDocMax; } #endif /* Pre-process each page */ p = 0; /* page_nr starts at 0 */ while (lengthPrinted < lengthDoc) { page_starts = (int*)iupArrayInc(page_starts_array); page_starts[p] = lengthPrinted; frPrint.chrg.cpMin = lengthPrinted; frPrint.chrg.cpMax = lengthDoc; lengthPrinted = (int)IupScintillaSendMessage(ih, SCI_FORMATRANGE, 0, (sptr_t)&frPrint); p++; } page_starts = (int*)iupArrayInc(page_starts_array); page_starts[p] = lengthPrinted; gtk_print_operation_set_n_pages(operation, p); } static void gtkScintillaDrawPage(GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, Ihandle* ih) { int lengthDoc; struct Sci_RangeToFormat frPrint; Iarray* page_starts_array = (Iarray*)iupAttribGet(ih, "_IUP_PAGE_ARRAY"); int* page_starts = (int*)iupArrayGetData(page_starts_array); gtkScintillaSetupFormat(&frPrint, context, ih); lengthDoc = (int)IupScintillaSendMessage(ih, SCI_GETLENGTH, 0, 0); frPrint.chrg.cpMin = page_starts[page_nr]; frPrint.chrg.cpMax = page_starts[page_nr + 1]; if (frPrint.chrg.cpMax < lengthDoc) frPrint.chrg.cpMax--; IupScintillaSendMessage(ih, SCI_FORMATRANGE, 1, (sptr_t)&frPrint); (void)operation; } int iupdrvScintillaPrintAttrib(Ihandle* ih, const char* value) { GtkPrintOperation *printOp = gtk_print_operation_new(); Iarray* page_starts_array = iupArrayCreate(10, sizeof(int)); int startPos = 0, endPos = 0; iupAttribSet(ih, "_IUP_PAGE_ARRAY", (char*)page_starts_array); g_signal_connect(printOp, "begin_print", G_CALLBACK(gtkScintillaBeginPrint), ih); g_signal_connect(printOp, "draw_page", G_CALLBACK(gtkScintillaDrawPage), ih); gtk_print_operation_set_job_name(printOp, iupgtkStrConvertToSystem(value)); /* See if a range has been selected */ IupGetIntInt(ih, "SELECTIONPOS", &startPos, &endPos); #if GTK_CHECK_VERSION(2, 18, 0) if (startPos == endPos) gtk_print_operation_set_support_selection(printOp, FALSE); else { gtk_print_operation_set_support_selection(printOp, TRUE); gtk_print_operation_set_has_selection(printOp, TRUE); } #endif if (!iupAttribGetBoolean(ih, "PRINTDIALOG")) gtk_print_operation_run(printOp, GTK_PRINT_OPERATION_ACTION_PRINT, GTK_WINDOW(IupGetDialog(ih)->handle), NULL); else gtk_print_operation_run(printOp, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW(IupGetDialog(ih)->handle), NULL); iupAttribSet(ih, "_IUP_PAGE_ARRAY", NULL); iupArrayDestroy(page_starts_array); g_object_unref(printOp); return 0; } /*****************************************************************************/ int idrvScintillaMap(Ihandle* ih) { ih->handle = scintilla_new(); if (!ih->handle) return IUP_ERROR; gtk_widget_show(ih->handle); /* add to the parent, all GTK controls must call this. */ iupgtkAddToParent(ih); if (!iupAttribGetBoolean(ih, "CANFOCUS")) iupgtkSetCanFocus(ih->handle, 0); g_signal_connect(G_OBJECT(ih->handle), "enter-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "leave-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "focus-in-event", G_CALLBACK(iupgtkFocusInOutEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "focus-out-event", G_CALLBACK(iupgtkFocusInOutEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "key-press-event", G_CALLBACK(iupgtkKeyPressEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "show-help", G_CALLBACK(iupgtkShowHelp), ih); g_signal_connect_after(G_OBJECT(ih->handle), "key-release-event", G_CALLBACK(gtkScintillaKeyReleaseEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "button-press-event", G_CALLBACK(gtkScintillaButtonEvent), ih); /* if connected "after" then it is ignored */ g_signal_connect(G_OBJECT(ih->handle), "button-release-event", G_CALLBACK(gtkScintillaButtonEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event", G_CALLBACK(iupgtkMotionNotifyEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "sci-notify", G_CALLBACK(gtkScintillaNotify), ih); gtk_widget_realize(ih->handle); return IUP_NOERROR; } void iupdrvScintillaReleaseMethod(Iclass* ic) { (void)ic; }