📄 editwidget.c
字号:
/* editor initialisation and callback handler.
Copyright (C) 1996, 1997 the Free Software Foundation
Authors: 1996, 1997 Paul Sheer
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include "edit.h"
#ifndef MIDNIGHT
#include <X11/Xmd.h> /* CARD32 */
#include <X11/Xatom.h>
#include "app_glob.c"
#include "coollocal.h"
#include "editcmddef.h"
#include "mousemark.h"
#endif
#ifndef MIDNIGHT
extern int EditExposeRedraw;
CWidget *wedit = 0;
void edit_destroy_callback (CWidget * w)
{
if (w) {
edit_clean (w->editor);
if (w->editor)
free (w->editor);
w->editor = NULL;
} else
/* NLS ? */
CError ("Trying to destroy non-existing editor widget.\n");
}
void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton);
extern int option_editor_bg_normal;
void edit_tri_cursor (Window win);
/* starting_directory is for the filebrowser */
CWidget *CDrawEditor (const char *identifier, Window parent, int x, int y,
int width, int height, const char *text, const char *filename,
const char *starting_directory, unsigned int options, unsigned long text_size)
{
static made_directory = 0;
int extra_space_for_hscroll = 0;
CWidget *w;
WEdit *e;
if (options & EDITOR_HORIZ_SCROLL)
extra_space_for_hscroll = 8;
wedit = w = CSetupWidget (identifier, parent, x, y,
width + 7, height + 6, C_EDITOR_WIDGET,
ExposureMask | ButtonPressMask | ButtonReleaseMask | \
KeyPressMask | KeyReleaseMask | ButtonMotionMask | \
PropertyChangeMask | StructureNotifyMask | \
EnterWindowMask | LeaveWindowMask, color_palette (option_editor_bg_normal), 1);
edit_tri_cursor (w->winid);
w->options = options | WIDGET_TAKES_SELECTION;
w->destroy = edit_destroy_callback;
if (filename)
w->label = strdup (filename);
else
w->label = strdup ("");
if (!made_directory) {
mkdir (catstrs (home_dir, EDIT_DIR, 0), 0700);
made_directory = 1;
}
e = w->editor = CMalloc (sizeof (WEdit));
if (!w->editor) {
/* Not essential to translate */
CError (_ ("Error initialising editor.\n"));
return 0;
}
w->editor->widget = w;
e = w->editor = edit_init (e, height / FONT_PIX_PER_LINE, width / FONT_MEAN_WIDTH, filename, text, starting_directory, text_size);
if (!e) {
CDestroyWidget (w->ident);
return 0;
}
e->macro_i = -1;
e->widget = w;
set_hint_pos (x + width + 7 + WIDGET_SPACING, y + height + 6 + WIDGET_SPACING + extra_space_for_hscroll);
if (extra_space_for_hscroll) {
w->hori_scrollbar = CDrawHorizontalScrollbar (catstrs (identifier, ".hsc", 0), parent,
x, y + height + 6, width + 6, 12, 0, 0);
CSetScrollbarCallback (w->hori_scrollbar->ident, w->ident, link_hscrollbar_to_editor);
}
if (!(options & EDITOR_NO_TEXT))
CDrawText (catstrs (identifier, ".text", 0), parent, x, y + height + 6 + WIDGET_SPACING + extra_space_for_hscroll, "%s", e->filename);
if (!(options & EDITOR_NO_SCROLL)) {
w->vert_scrollbar = CDrawVerticalScrollbar (catstrs (identifier, ".vsc", 0), parent,
x + width + 7 + WIDGET_SPACING, y, height + 6, 20, 0, 0);
CSetScrollbarCallback (w->vert_scrollbar->ident, w->ident, link_scrollbar_to_editor);
}
return w;
}
void update_scroll_bars (WEdit * e)
{
int i, x1, x2;
CWidget *scroll;
scroll = e->widget->vert_scrollbar;
if (scroll) {
i = e->total_lines - e->start_line + 1;
if (i > e->num_widget_lines)
i = e->num_widget_lines;
if (e->total_lines) {
x1 = (double) 65535.0 *e->start_line / (e->total_lines + 1);
x2 = (double) 65535.0 *i / (e->total_lines + 1);
} else {
x1 = 0;
x2 = 65535;
}
if (x1 != scroll->firstline || x2 != scroll->numlines) {
scroll->firstline = x1;
scroll->numlines = x2;
EditExposeRedraw = 1;
render_scrollbar (scroll);
EditExposeRedraw = 0;
}
}
scroll = e->widget->hori_scrollbar;
if (scroll) {
i = e->max_column - (-e->start_col) + 1;
if (i > e->num_widget_columns * FONT_MEAN_WIDTH)
i = e->num_widget_columns * FONT_MEAN_WIDTH;
x1 = (double) 65535.0 *(-e->start_col) / (e->max_column + 1);
x2 = (double) 65535.0 *i / (e->max_column + 1);
if (x1 != scroll->firstline || x2 != scroll->numlines) {
scroll->firstline = x1;
scroll->numlines = x2;
EditExposeRedraw = 1;
render_scrollbar (scroll);
EditExposeRedraw = 0;
}
}
}
/* returns the position in the edit buffer of a window click */
long edit_get_click_pos (WEdit * edit, int x, int y)
{
long click;
/* (1) goto to left margin */
click = edit_bol (edit, edit->curs1);
/* (1) move up or down */
if (y > (edit->curs_row + 1))
click = edit_move_forward (edit, click, y - (edit->curs_row + 1), 0);
if (y < (edit->curs_row + 1))
click = edit_move_backward (edit, click, (edit->curs_row + 1) - y);
/* (3) move right to x pos */
click = edit_move_forward3 (edit, click, x - edit->start_col - 1, 0);
return click;
}
void edit_translate_xy (int xs, int ys, int *x, int *y)
{
*x = xs - EDIT_TEXT_HORIZONTAL_OFFSET;
*y = (ys - EDIT_TEXT_VERTICAL_OFFSET - option_text_line_spacing / 2 - 1) / FONT_PIX_PER_LINE + 1;
}
extern int just_dropped_something;
static void mouse_redraw (WEdit * edit, long click)
{
edit->force |= REDRAW_PAGE | REDRAW_LINE;
edit_update_curs_row (edit);
edit_update_curs_col (edit);
edit->prev_col = edit_get_col (edit);
edit_update_screen (edit);
edit->search_start = click;
}
static void xy (int x, int y, int *x_return, int *y_return)
{
edit_translate_xy (x, y, x_return, y_return);
}
static long cp (WEdit *edit, int x, int y)
{
return edit_get_click_pos (edit, x, y);
}
/* return 1 if not marked */
static int marks (WEdit * edit, long *start, long *end)
{
return eval_marks (edit, start, end);
}
int column_highlighting = 0;
static int erange (WEdit * edit, long start, long end, int click)
{
if (column_highlighting) {
int x;
x = edit_move_forward3 (edit, edit_bol (edit, click), 0, click);
if ((x >= edit->column1 && x < edit->column2)
|| (x > edit->column2 && x <= edit->column1))
return (start <= click && click < end);
else
return 0;
}
return (start <= click && click < end);
}
static void fin_mark (WEdit *edit)
{
if (edit->mark2 < 0)
edit_mark_cmd (edit, 0);
}
static void move_mark (WEdit *edit)
{
edit_mark_cmd (edit, 1);
edit_mark_cmd (edit, 0);
}
static void release_mark (WEdit *edit, XEvent *event)
{
if (edit->mark2 < 0)
edit_mark_cmd (edit, 0);
else
edit_mark_cmd (edit, 1);
if (edit->mark1 != edit->mark2) {
edit_get_selection (edit);
XSetSelectionOwner (CDisplay, XA_PRIMARY, edit->widget->winid, event->xbutton.time);
}
}
static char *get_block (WEdit * edit, long start_mark, long end_mark, int *type, int *l)
{
char *t;
t = (char *) edit_get_block (edit, start_mark, end_mark, l);
if (strlen (t) < *l)
*type = DndRawData; /* if there are nulls in the data, send as raw */
else
*type = DndText; /* else send as text */
return t;
}
static void move (WEdit *edit, long click, int y)
{
edit_cursor_move (edit, click - edit->curs1);
}
static void dclick (WEdit *edit, XEvent *event)
{
edit_mark_cmd (edit, 1);
edit_right_word_move (edit);
edit_mark_cmd (edit, 0);
edit_left_word_move (edit);
release_mark (edit, event);
}
static void redraw (WEdit *edit, long click)
{
mouse_redraw (edit, click);
}
static void edit_mouse_mark (WEdit * edit, XEvent * event, CEvent * ce)
{
edit_update_curs_row (edit);
edit_update_curs_col (edit);
if (event->type != MotionNotify) {
edit_push_action (edit, KEY_PRESS + edit->start_display);
if (edit->mark2 == -1)
edit_push_action (edit, MARK_1 + edit->mark1); /* mark1 must be following the cursor */
}
if (event->type == ButtonPress) {
edit->highlight = 0;
edit->found_len = 0;
}
mouse_mark (
(void *) edit,
event,
ce,
(void (*) (int, int, int *, int *)) xy,
(long (*) (void *, int, int)) cp,
(int (*) (void *, long *, long *)) marks,
(int (*) (void *, long, long, long)) erange,
(void (*) (void *)) fin_mark,
(void (*) (void *)) move_mark,
(void (*) (void *, XEvent *)) release_mark,
(char * (*) (void *, long, long, int *, int *)) get_block,
(void (*) (void *, long, int)) move,
0,
(void (*) (void *, XEvent *)) dclick,
(void (*) (void *, long)) redraw
);
}
void link_scrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
{
int i, start_line;
WEdit *e;
e = editor->editor;
if (!e)
return;
if (!e->widget->vert_scrollbar)
return;
start_line = e->start_line;
if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
edit_move_display (e, (double) scrollbar->firstline * e->total_lines / 65535.0 + 1);
} else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
switch (whichscrbutton) {
case 1:
edit_move_display (e, e->start_line - e->num_widget_lines + 1);
break;
case 2:
edit_move_display (e, e->start_line - 1);
break;
case 5:
edit_move_display (e, e->start_line + 1);
break;
case 4:
edit_move_display (e, e->start_line + e->num_widget_lines - 1);
break;
}
}
if (e->total_lines)
scrollbar->firstline = (double) 65535.0 *e->start_line / (e->total_lines + 1);
else
scrollbar->firstline = 0;
i = e->total_lines - e->start_line + 1;
if (i > e->num_widget_lines)
i = e->num_widget_lines;
if (e->total_lines)
scrollbar->numlines = (double) 65535.0 *i / (e->total_lines + 1);
else
scrollbar->numlines = 65535;
if (start_line != e->start_line) {
e->force |= REDRAW_PAGE | REDRAW_LINE;
set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
if (CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0))
return;
}
if (e->force) {
edit_render_keypress (e);
edit_status (e);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -