📄 scintillagtk.cxx
字号:
bool modified = false;
int pageScroll = LinesToScroll();
if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) ||
GTK_ADJUSTMENT(adjustmentv)->page_size != nPage ||
GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) {
GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1;
GTK_ADJUSTMENT(adjustmentv)->page_size = nPage;
GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll;
gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv));
modified = true;
}
PRectangle rcText = GetTextRectangle();
int horizEndPreferred = scrollWidth;
if (horizEndPreferred < 0)
horizEndPreferred = 0;
unsigned int pageWidth = rcText.Width();
if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred ||
GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth) {
GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred;
GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth;
gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth));
modified = true;
}
return modified;
}
void ScintillaGTK::ReconfigureScrollBars() {
PRectangle rc = wMain.GetClientPosition();
Resize(rc.Width(), rc.Height());
}
void ScintillaGTK::NotifyChange() {
gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
}
void ScintillaGTK::NotifyFocus(bool focus) {
gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
Platform::LongFromTwoShorts(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
}
void ScintillaGTK::NotifyParent(SCNotification scn) {
scn.nmhdr.hwndFrom = PWidget(wMain);
scn.nmhdr.idFrom = GetCtrlID();
gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL],
GetCtrlID(), &scn);
}
void ScintillaGTK::NotifyKey(int key, int modifiers) {
SCNotification scn;
scn.nmhdr.code = SCN_KEY;
scn.ch = key;
scn.modifiers = modifiers;
NotifyParent(scn);
}
void ScintillaGTK::NotifyURIDropped(const char *list) {
SCNotification scn;
scn.nmhdr.code = SCN_URIDROPPED;
scn.text = list;
NotifyParent(scn);
}
const char *CharacterSetID(int characterSet);
int ScintillaGTK::KeyDefault(int key, int modifiers) {
if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) {
#if GTK_MAJOR_VERSION >= 2
char utfVal[4]="\0\0\0";
wchar_t wcs[2];
wcs[0] = gdk_keyval_to_unicode(key);
wcs[1] = 0;
UTF8FromUCS2(wcs, 1, utfVal, 3);
if (key <= 0xFE00) {
if (IsUnicodeMode()) {
AddCharUTF(utfVal,strlen(utfVal));
return 1;
} else {
const char *source =
CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
if (*source) {
iconv_t iconvh = iconv_open("UTF8", source);
if (iconvh != ((iconv_t)(-1))) {
char localeVal[4]="\0\0\0";
char *pin = utfVal;
size_t inLeft = strlen(utfVal);
char *pout = localeVal;
size_t outLeft = sizeof(localeVal);
size_t conversions = iconv(iconvh, &pin, &inLeft, &pout, &outLeft);
iconv_close(iconvh);
if (conversions != ((size_t)(-1))) {
*pout = '\0';
for (int i=0; localeVal[i]; i++) {
AddChar(localeVal[i]);
}
return 1;
}
}
}
}
}
#endif
if (key < 256) {
AddChar(key);
return 1;
} else {
// Pass up to container in case it is an accelerator
NotifyKey(key, modifiers);
return 0;
}
} else {
// Pass up to container in case it is an accelerator
NotifyKey(key, modifiers);
return 0;
}
//Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
}
void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
copyText.Copy(selectedText.s, selectedText.len);
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
clipboard_atom,
GDK_CURRENT_TIME);
}
void ScintillaGTK::Copy() {
if (currentPos != anchor) {
CopySelectionRange(©Text);
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
clipboard_atom,
GDK_CURRENT_TIME);
#if PLAT_GTK_WIN32
if (selType == selRectangle) {
::OpenClipboard(NULL);
::SetClipboardData(cfColumnSelect, 0);
::CloseClipboard();
}
#endif
}
}
void ScintillaGTK::Paste() {
gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
clipboard_atom,
gdk_atom_intern("STRING", FALSE), GDK_CURRENT_TIME);
}
void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
if (!ct.wCallTip.Created()) {
ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
ct.wDraw = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), PWidget(ct.wDraw));
gtk_signal_connect(GTK_OBJECT(PWidget(ct.wDraw)), "expose_event",
GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
gtk_signal_connect(GTK_OBJECT(PWidget(ct.wDraw)), "button_press_event",
GtkSignalFunc(ScintillaGTK::PressCT), static_cast<void *>(this));
gtk_widget_set_events(PWidget(ct.wDraw),
GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
}
gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct.wDraw)),
rc.Width(), rc.Height());
ct.wDraw.Show();
ct.wCallTip.Show();
//gtk_widget_set_usize(PWidget(ct.wCallTip), rc.Width(), rc.Height());
gdk_window_resize(PWidget(ct.wCallTip)->window, rc.Width(), rc.Height());
}
void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
char fulllabel[200];
strcpy(fulllabel, "/");
strcat(fulllabel, label);
GtkItemFactoryCallback menuSig = GtkItemFactoryCallback(PopUpCB);
GtkItemFactoryEntry itemEntry = {
fulllabel, NULL,
menuSig,
cmd,
const_cast<gchar *>(label[0] ? "<Item>" : "<Separator>"),
#if GTK_MAJOR_VERSION >= 2
NULL
#endif
};
gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup.GetID()),
&itemEntry, this, 1);
if (cmd) {
GtkWidget *item = gtk_item_factory_get_widget_by_action(
reinterpret_cast<GtkItemFactory *>(popup.GetID()), cmd);
if (item)
gtk_widget_set_sensitive(item, enabled);
}
}
bool ScintillaGTK::OwnPrimarySelection() {
return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY)
== GTK_WIDGET(PWidget(wMain))->window) &&
(GTK_WIDGET(PWidget(wMain))->window != NULL));
}
void ScintillaGTK::ClaimSelection() {
// X Windows has a 'primary selection' as well as the clipboard.
// Whenever the user selects some text, we become the primary selection
if (currentPos != anchor) {
primarySelection = true;
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
primary.Set(0, 0);
} else if (OwnPrimarySelection()) {
primarySelection = true;
if (primary.s == NULL)
gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
} else {
primarySelection = false;
primary.Set(0, 0);
}
}
char *ScintillaGTK::GetGtkSelectionText(const GtkSelectionData *selectionData,
unsigned int* len, bool* isRectangular) {
char *dest;
unsigned int i;
const char *sptr;
char *dptr;
// Return empty string if selection is not a string
if (selectionData->type != GDK_TARGET_STRING) {
dest = new char[1];
strcpy(dest, "");
*isRectangular = false;
*len = 0;
return dest;
}
// Need to convert to correct newline form for this file: win32gtk *always* returns
// only \n line delimiter from clipboard, and linux/unix gtk may also not send the
// form that matches the document (this is probably not effectively standardized by X)
dest = new char[(2 * static_cast<unsigned int>(selectionData->length)) + 1];
sptr = reinterpret_cast<const char *>(selectionData->data);
dptr = dest;
for (i = 0; i < static_cast<unsigned int>(selectionData->length) && *sptr != '\0'; i++) {
if (*sptr == '\n' || *sptr == '\r') {
if (pdoc->eolMode == SC_EOL_CR) {
*dptr++ = '\r';
}
else if (pdoc->eolMode == SC_EOL_LF) {
*dptr++ = '\n';
}
else { // pdoc->eolMode == SC_EOL_CRLF
*dptr++ = '\r';
*dptr++ = '\n';
}
if (*sptr == '\r' && i+1 < static_cast<unsigned int>(selectionData->length) && *(sptr+1) == '\n') {
i++;
sptr++;
}
sptr++;
}
else {
*dptr++ = *sptr++;
}
}
*dptr++ = '\0';
*len = (dptr - dest) - 1;
// Check for "\n\0" ending to string indicating that selection is rectangular
#if PLAT_GTK_WIN32
*isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
#else
*isRectangular = ((selectionData->length > 2) &&
(selectionData->data[selectionData->length - 1] == 0 &&
selectionData->data[selectionData->length - 2] == '\n'));
#endif
return dest;
}
void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
if (selection_data->type == GDK_TARGET_STRING) {
//Platform::DebugPrintf("Received String Selection %x %d\n", selection_data->selection, selection_data->length);
if (((selection_data->selection == clipboard_atom) ||
(selection_data->selection == GDK_SELECTION_PRIMARY)) &&
(selection_data->length > 0)) {
unsigned int len;
bool isRectangular;
char *ptr = GetGtkSelectionText(selection_data, &len, &isRectangular);
pdoc->BeginUndoAction();
int selStart = SelectionStart();
if (selection_data->selection != GDK_SELECTION_PRIMARY) {
ClearSelection();
}
if (isRectangular) {
PasteRectangular(selStart, ptr, len);
} else {
pdoc->InsertString(currentPos, ptr, len);
SetEmptySelection(currentPos + len);
}
pdoc->EndUndoAction();
delete []ptr;
}
}
Redraw();
}
void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
dragWasDropped = true;
if (selection_data->type == GDK_TARGET_STRING) {
if (selection_data->length > 0) {
unsigned int len;
bool isRectangular;
char *ptr = GetGtkSelectionText(selection_data, &len, &isRectangular);
DropAt(posDrop, ptr, false, isRectangular);
delete []ptr;
}
} else {
char *ptr = reinterpret_cast<char *>(selection_data->data);
NotifyURIDropped(ptr);
}
Redraw();
}
void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
if (selection_data->selection == GDK_SELECTION_PRIMARY) {
if (primary.s == NULL) {
CopySelectionRange(&primary);
}
text = &primary;
}
char *selBuffer = text->s;
#if PLAT_GTK_WIN32
// win32gtk requires \n delimited lines and doesn't work right with
// other line formats, so make a copy of the clip text now with
// newlines converted
char *tmpstr = new char[text->len + 1];
char *sptr = selBuffer;
char *dptr = tmpstr;
while (*sptr != '\0') {
if (pdoc->eolMode == SC_EOL_CR && *sptr == '\r') {
*dptr++ = '\n';
sptr++;
}
else if (pdoc->eolMode != SC_EOL_CR && *sptr == '\r') {
sptr++;
}
else {
*dptr++ = *sptr++;
}
}
*dptr = '\0';
selBuffer = tmpstr;
#endif
if (info == TARGET_STRING) {
int len = strlen(selBuffer);
// Here is a somewhat evil kludge.
// As I can not work out how to store data on the clipboard in multiple formats
// and need some way to mark the clipping as being stream or rectangular,
// the terminating \0 is included in the length for rectangular clippings.
// All other tested aplications behave benignly by ignoring the \0.
// The #if is here because on Windows cfColumnSelect clip entry is used
// instead as standard indicator of rectangularness (so no need to kludge)
#if PLAT_GTK_WIN32 == 0
if (text->rectangular)
len++;
#endif
gtk_selection_data_set(selection_data, GDK_SELECTION_TYPE_STRING,
8, reinterpret_cast<unsigned char *>(selBuffer),
len);
} else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT)) {
guchar *text;
GdkAtom encoding;
gint format;
gint new_length;
gdk_string_to_compound_text(reinterpret_cast<char *>(selBuffer),
&encoding, &format, &text, &new_length);
gtk_selection_data_set(selection_data, encoding, format, text, new_length);
gdk_free_compound_text(text);
}
#if PLAT_GTK_WIN32
delete []tmpstr;
#endif
}
void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {
//Platform::DebugPrintf("UnclaimSelection\n");
if (selection_event->selection == GDK_SELECTION_PRIMARY) {
//Platform::DebugPrintf("UnclaimPrimarySelection\n");
if (!OwnPrimarySelection()) {
primary.Set(0, 0);
primarySelection = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -