📄 scintillagtk.cxx
字号:
FullPaint();
}
}
}
void ScintillaGTK::Resize(int width, int height) {
//Platform::DebugPrintf("Resize %d %d\n", width, height);
//printf("Resize %d %d\n", width, height);
// Not always needed, but some themes can have different sizes of scrollbars
scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width;
scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height;
// These allocations should never produce negative sizes as they would wrap around to huge
// unsigned numbers inside GTK+ causing warnings.
bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone);
int horizontalScrollBarHeight = scrollBarHeight;
if (!showSBHorizontal)
horizontalScrollBarHeight = 0;
int verticalScrollBarHeight = scrollBarWidth;
if (!verticalScrollBarVisible)
verticalScrollBarHeight = 0;
GtkAllocation alloc;
alloc.x = 0;
if (showSBHorizontal) {
alloc.y = height - scrollBarHeight;
alloc.width = Platform::Maximum(1, width - scrollBarWidth) + 1;
alloc.height = horizontalScrollBarHeight;
} else {
alloc.y = -scrollBarHeight;
alloc.width = 0;
alloc.height = 0;
}
gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc);
alloc.y = 0;
if (verticalScrollBarVisible) {
alloc.x = width - scrollBarWidth;
alloc.width = scrollBarWidth;
alloc.height = Platform::Maximum(1, height - scrollBarHeight) + 1;
if (!showSBHorizontal)
alloc.height += scrollBarWidth-1;
} else {
alloc.x = -scrollBarWidth;
alloc.width = 0;
alloc.height = 0;
}
gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc);
if (GTK_WIDGET_MAPPED(PWidget(wMain))) {
ChangeSize();
}
alloc.x = 0;
alloc.y = 0;
alloc.width = Platform::Maximum(1, width - scrollBarWidth);
alloc.height = Platform::Maximum(1, height - scrollBarHeight);
if (!showSBHorizontal)
alloc.height += scrollBarWidth;
gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc);
}
static void SetAdjustmentValue(GtkObject *object, int value) {
GtkAdjustment *adjustment = GTK_ADJUSTMENT(object);
int maxValue = static_cast<int>(
adjustment->upper - adjustment->page_size);
if (value > maxValue)
value = maxValue;
if (value < 0)
value = 0;
gtk_adjustment_set_value(adjustment, value);
}
gint ScintillaGTK::PressThis(GdkEventButton *event) {
//Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
// Do not use GTK+ double click events as Scintilla has its own double click detection
if (event->type != GDK_BUTTON_PRESS)
return FALSE;
evbtn = *event;
Point pt;
pt.x = int(event->x);
pt.y = int(event->y);
PRectangle rcClient = GetClientRectangle();
//Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n",
// pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) {
Platform::DebugPrintf("Bad location\n");
return FALSE;
}
bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
gtk_widget_grab_focus(PWidget(wMain));
if (event->button == 1) {
//ButtonDown(pt, event->time,
// event->state & GDK_SHIFT_MASK,
// event->state & GDK_CONTROL_MASK,
// event->state & GDK_MOD1_MASK);
// Instead of sending literal modifiers use control instead of alt
// This is because all the window managers seem to grab alt + click for moving
ButtonDown(pt, event->time,
(event->state & GDK_SHIFT_MASK) != 0,
(event->state & GDK_CONTROL_MASK) != 0,
(event->state & GDK_CONTROL_MASK) != 0);
} else if (event->button == 2) {
// Grab the primary selection if it exists
Position pos = PositionFromLocation(pt);
if (OwnPrimarySelection() && primary.s == NULL)
CopySelectionRange(&primary);
SetSelection(pos, pos);
gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
gdk_atom_intern("STRING", FALSE), event->time);
} else if (event->button == 3) {
if (displayPopupMenu) {
// PopUp menu
// Convert to screen
int ox = 0;
int oy = 0;
gdk_window_get_origin(PWidget(wMain)->window, &ox, &oy);
ContextMenu(Point(pt.x + ox, pt.y + oy));
} else {
return FALSE;
}
} else if (event->button == 4) {
// Wheel scrolling up (only xwin gtk does it this way)
if (ctrl)
SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6);
else
SetAdjustmentValue(adjustmentv, topLine - 3);
} else if (event->button == 5) {
// Wheel scrolling down (only xwin gtk does it this way)
if (ctrl)
SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6);
else
SetAdjustmentValue(adjustmentv, topLine + 3);
}
#if GTK_MAJOR_VERSION >= 2
return TRUE;
#else
return FALSE;
#endif
}
gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) {
if (event->window != widget->window)
return FALSE;
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
return sciThis->PressThis(event);
}
gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
//Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state);
if (!sciThis->HaveMouseCapture())
return FALSE;
if (event->button == 1) {
Point pt;
pt.x = int(event->x);
pt.y = int(event->y);
//Platform::DebugPrintf("Up %x %x %d %d %d\n",
// sciThis,event->window,event->time, pt.x, pt.y);
if (event->window != PWidget(sciThis->wMain)->window)
// If mouse released on scroll bar then the position is relative to the
// scrollbar, not the drawing window so just repeat the most recent point.
pt = sciThis->ptMouseLast;
sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0);
}
return FALSE;
}
// win32gtk has a special wheel mouse event for whatever reason and doesn't
// use the button4/5 trick used under X windows.
#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
GdkEventScroll *event) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
if (widget == NULL || event == NULL)
return FALSE;
// Compute amount and direction to scroll (even tho on win32 there is
// intensity of scrolling info in the native message, gtk doesn't
// support this so we simulate similarly adaptive scrolling)
int cLineScroll;
int timeDelta = 1000000;
GTimeVal curTime;
g_get_current_time(&curTime);
if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec)
timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec;
else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1)
timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec);
if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) {
if (sciThis->wheelMouseIntensity < 12)
sciThis->wheelMouseIntensity++;
cLineScroll = sciThis->wheelMouseIntensity;
} else {
cLineScroll = sciThis->linesPerScroll;
if (cLineScroll == 0)
cLineScroll = 4;
sciThis->wheelMouseIntensity = cLineScroll;
}
if (event->direction == GDK_SCROLL_UP) {
cLineScroll *= -1;
}
g_get_current_time(&sciThis->lastWheelMouseTime);
sciThis->lastWheelMouseDirection = event->direction;
// Note: Unpatched versions of win32gtk don't set the 'state' value so
// only regular scrolling is supported there. Also, unpatched win32gtk
// issues spurious button 2 mouse events during wheeling, which can cause
// problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
// Data zoom not supported
if (event->state & GDK_SHIFT_MASK) {
return FALSE;
}
// Text font size zoom
if (event->state & GDK_CONTROL_MASK) {
if (cLineScroll < 0) {
sciThis->KeyCommand(SCI_ZOOMIN);
return TRUE;
} else {
sciThis->KeyCommand(SCI_ZOOMOUT);
return TRUE;
}
// Regular scrolling
} else {
sciThis->ScrollTo(sciThis->topLine + cLineScroll);
return TRUE;
}
}
#endif
gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
//Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time);
if (event->window != widget->window)
return FALSE;
int x = 0;
int y = 0;
GdkModifierType state;
if (event->is_hint) {
gdk_window_get_pointer(event->window, &x, &y, &state);
} else {
x = static_cast<int>(event->x);
y = static_cast<int>(event->y);
state = static_cast<GdkModifierType>(event->state);
}
//Platform::DebugPrintf("Move %x %x %d %c %d %d\n",
// sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y);
Point pt(x, y);
sciThis->ButtonMove(pt);
return FALSE;
}
// Map the keypad keys to their equivalent functions
static int KeyTranslate(int keyIn) {
switch (keyIn) {
case GDK_ISO_Left_Tab:
return SCK_TAB;
case GDK_KP_Down:
return SCK_DOWN;
case GDK_KP_Up:
return SCK_UP;
case GDK_KP_Left:
return SCK_LEFT;
case GDK_KP_Right:
return SCK_RIGHT;
case GDK_KP_Home:
return SCK_HOME;
case GDK_KP_End:
return SCK_END;
case GDK_KP_Page_Up:
return SCK_PRIOR;
case GDK_KP_Page_Down:
return SCK_NEXT;
case GDK_KP_Delete:
return SCK_DELETE;
case GDK_KP_Insert:
return SCK_INSERT;
case GDK_KP_Enter:
return SCK_RETURN;
case GDK_Down:
return SCK_DOWN;
case GDK_Up:
return SCK_UP;
case GDK_Left:
return SCK_LEFT;
case GDK_Right:
return SCK_RIGHT;
case GDK_Home:
return SCK_HOME;
case GDK_End:
return SCK_END;
case GDK_Page_Up:
return SCK_PRIOR;
case GDK_Page_Down:
return SCK_NEXT;
case GDK_Delete:
return SCK_DELETE;
case GDK_Insert:
return SCK_INSERT;
case GDK_Escape:
return SCK_ESCAPE;
case GDK_BackSpace:
return SCK_BACK;
case GDK_Tab:
return SCK_TAB;
case GDK_Return:
return SCK_RETURN;
case GDK_KP_Add:
return SCK_ADD;
case GDK_KP_Subtract:
return SCK_SUBTRACT;
case GDK_KP_Divide:
return SCK_DIVIDE;
default:
return keyIn;
}
}
gint ScintillaGTK::KeyThis(GdkEventKey *event) {
//Platform::DebugPrintf("SC-key: %d %x [%s]\n",
// event->keyval, event->state, (event->length > 0) ? event->string : "empty");
bool shift = (event->state & GDK_SHIFT_MASK) != 0;
bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
bool alt = (event->state & GDK_MOD1_MASK) != 0;
int key = event->keyval;
if (ctrl && (key < 128))
key = toupper(key);
else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9))
key &= 0x7F;
// Hack for keys over 256 and below command keys but makes Hungarian work.
// This will have to change for Unicode
else if (key >= 0xFE00)
key = KeyTranslate(key);
else if (IsUnicodeMode())
; // No operation
else if ((key >= 0x100) && (key < 0x1000))
key &= 0xff;
bool consumed = false;
bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0;
if (!consumed)
consumed = added;
//Platform::DebugPrintf("SK-key: %d %x %x\n",event->keyval, event->state, consumed);
if (event->keyval == 0xffffff && event->length > 0) {
ClearSelection();
if (pdoc->InsertString(CurrentPosition(), event->string)) {
MovePositionTo(CurrentPosition() + event->length);
}
}
return consumed;
}
gint ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
return sciThis->KeyThis(event);
}
gint ScintillaGTK::KeyRelease(GtkWidget *, GdkEventKey * /*event*/) {
//Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string);
return FALSE;
}
void ScintillaGTK::Destroy(GtkObject* object) {
ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(object);
// This avoids a double destruction
if (!scio->pscin)
return;
ScintillaGTK *sciThis = reinterpret_cast<ScintillaGTK *>(scio->pscin);
//Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
sciThis->Finalise();
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
delete sciThis;
scio->pscin = 0;
}
static void DrawChild(GtkWidget *widget, GdkRectangle *area) {
GdkRectangle areaIntersect;
if (widget &&
GTK_WIDGET_DRAWABLE(widget) &&
gtk_widget_intersect(widget, area, &areaIntersect)) {
gtk_widget_draw(widget, &areaIntersect);
}
}
void ScintillaGTK::Draw(GtkWidget *widget, GdkRectangle *area) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -