📄 fieldedtextbox.c
字号:
/* fieldedtextbox.c - for drawing a scrollable text window widget Copyright (C) 1996-2000 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. *//* * format: * * the printed fields can have the following: * * '\t': can only occur at the begining and end, or at the beginning. * At the beginning signals right justification. At the beginning * and the end signals centering. eg "\tcentred\t" or "\tleft" * "\v%d": insert pixmap %d at the point. Pixmaps are a special variety * defined by the create_text_pixmap() function. The value passed * to this function must appear after the \v and must be less * than 128. * "\f%d": advance forward %d pixels. %d must be less than 128. * "\r%c": puts %c in 'italic' color, default: green. * "\b%c": puts %c in 'bold' color, default: blue. */#define BDR 8#include <config.h>#include <stdio.h>#include <my_string.h>#include <stdlib.h>#include <stdarg.h>#include <X11/Intrinsic.h>#include <X11/Xatom.h>#include "lkeysym.h"#include "stringtools.h"#include "app_glob.c"#include "edit.h"#include "editcmddef.h"#include "coolwidget.h"#include "coollocal.h"#include "mousemark.h"#include "pool.h"#include "mad.h"extern struct look *look;extern int option_text_fg_normal;extern int option_text_fg_bold;extern int option_text_fg_italic;extern int option_text_bg_normal;extern int option_text_bg_marked;extern int option_text_bg_highlighted;/* for this widget ->column holds the pixel width of the longest line *//* char ** (*get_line) (void *data, int line_number, int *num_fields, int *tagged); */#define pixmap_width(x) 0int eh_fielded_textbox (CWidget * w, XEvent * xevent, CEvent * cwevent);static int calc_text_pos_fielded_textbox (CWidget * w, long b, long *q, int l);/* these are not printable in this module */#define this_is_printable(c) (!strchr ("\r\b\t", c))static int this_text_width (char *s){ int l = 0; char *p; for (p = s; *p; p++) { if (*p == '\v') l += pixmap_width (++p); else if (*p == '\f') l += *(++p); else if (this_is_printable (*p)) l += FONT_PER_CHAR((unsigned char) *p); } return l;}#define INTER_FIELD_SPACING 6#define LINE_OFFSET 0/* result must be free'd */static int *get_field_sizes (void *data, int *num_lines, int *max_width, char **(*get_line) (void *, int, int *, int *)){ char **fields; int tagged, i, tab[256], *result, num_fields, max_num_fields = 0, line_number; memset (tab, 0, sizeof (tab)); *num_lines = 0; for (line_number = 0;; line_number++) { fields = (*get_line) (data, line_number, &num_fields, &tagged); if (!fields) break; (*num_lines)++; if (max_num_fields < num_fields) max_num_fields = num_fields; for (i = 0; i < num_fields; i++) { int l; if (!fields[i]) break; l = this_text_width (fields[i]); if (tab[i] < l) tab[i] = l; } } *max_width = 0; for (i = 0; i < max_num_fields; i++) tab[i] += INTER_FIELD_SPACING; for (i = 0; i < max_num_fields; i++) *max_width += tab[i]; result = CMalloc (max_num_fields * sizeof (int)); memcpy (result, tab, max_num_fields * sizeof (int)); tab[max_num_fields] = 0; return result;}static void compose_line (void *data, int line_number, unsigned char *line, int *tab, char **(*get_line) (void *, int, int *, int *), int *tagged){ char **fields; int i, num_fields; *line = 0; *tagged = 0; if (!data) return; fields = (*get_line) (data, line_number, &num_fields, tagged); if (!fields) return; for (i = 0; i < num_fields; i++) { int l = 0, t, centred = 0; char *p; p = fields[i]; t = tab[i] - this_text_width (p) - INTER_FIELD_SPACING; if (t < 0) t = 0; if (p[0] == '\t') { p++; if (p[strlen (p) - 1] == '\t') { l = t - (t / 2); t /= 2; centred = 1; } else { l = t; t = 0; } } for (;;) { l -= 127; if (l >= 0) { *line++ = '\f'; *line++ = (unsigned char) 127; } else { l += 127; if (l) { *line++ = '\f'; *line++ = (unsigned char) l; } break; } } strcpy ((char *) line, p); line += strlen (p) - centred; if (!fields[i + 1]) break; t += INTER_FIELD_SPACING; for (;;) { t -= 127; if (t >= 0) { *line++ = '\f'; *line++ = (unsigned char) 127; } else { t += 127; if (t) { *line++ = '\f'; *line++ = (unsigned char) t; } break; } } } *line = 0;}static unsigned char *compose_line_cached (void *data, int l, int *tab, char **(*get_line) (void *, int, int *, int *), int *tagged){ static unsigned char line[4096]; static int c_tagged, c_l = -1; if (c_l == l) { *tagged = c_tagged; return line; } compose_line (data, l, line, tab, get_line, tagged); c_l = l; c_tagged = *tagged; return line;}static long count_fielded_textbox_lines (CWidget * wdt);void render_fielded_textbox (CWidget * w, int redrawall);void link_scrollbar_to_fielded_textbox (CWidget * scrollbar, CWidget * textbox, XEvent * xevent, CEvent * cwevent, int whichscrbutton){ int redrawtext = 0, count, c; static int r = 0; if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) { redrawtext = CSetTextboxPos (textbox, TEXT_SET_LINE, (double) scrollbar->firstline * textbox->numlines / 65535.0); } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) { switch (whichscrbutton) { case 1: redrawtext = CSetTextboxPos (textbox, TEXT_SET_LINE, textbox->firstline - (textbox->height / FONT_PIX_PER_LINE - 2)); break; case 2: redrawtext = CSetTextboxPos (textbox, TEXT_SET_LINE, textbox->firstline - 1); break; case 5: redrawtext = CSetTextboxPos (textbox, TEXT_SET_LINE, textbox->firstline + 1); break; case 4: redrawtext = CSetTextboxPos (textbox, TEXT_SET_LINE, textbox->firstline + (textbox->height / FONT_PIX_PER_LINE - 2)); break; } } if (xevent->type == ButtonRelease) render_fielded_textbox (textbox, 0); else { c = CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0); if (redrawtext) { if (!c) { render_fielded_textbox (textbox, 0); r = 0; } else { r = 1; } } else if (c && r) { render_fielded_textbox (textbox, 0); r = 0; } } count = count_fielded_textbox_lines (textbox); if (!count) count = 1; scrollbar->firstline = (double) 65535.0 *textbox->firstline / (textbox->numlines ? textbox->numlines : 1); scrollbar->numlines = (double) 65535.0 *count / (textbox->numlines ? textbox->numlines : 1);}void link_h_scrollbar_to_fielded_textbox (CWidget * scrollbar, CWidget * textbox, XEvent * xevent, CEvent * cwevent, int whichscrbutton){ int redrawtext = 0, c; static int r = 0; if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) { redrawtext = CSetTextboxPos (textbox, TEXT_SET_COLUMN, (double) scrollbar->firstline * (textbox->column / FONT_MEAN_WIDTH) / 65535.0); } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) { switch (whichscrbutton) { case 1: redrawtext = CSetTextboxPos (textbox, TEXT_SET_COLUMN, textbox->firstcolumn - (textbox->width / FONT_MEAN_WIDTH - 2)); break; case 2: redrawtext = CSetTextboxPos (textbox, TEXT_SET_COLUMN, textbox->firstcolumn - 1); break; case 5: redrawtext = CSetTextboxPos (textbox, TEXT_SET_COLUMN, textbox->firstcolumn + 1); break; case 4: redrawtext = CSetTextboxPos (textbox, TEXT_SET_COLUMN, textbox->firstcolumn + (textbox->width / FONT_MEAN_WIDTH - 2)); break; } } if (xevent->type == ButtonRelease) render_fielded_textbox (textbox, 0); else { c = CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0); if (redrawtext) { if (!c) { render_fielded_textbox (textbox, 0); r = 0; } else { r = 1; } } else if (c && r) { render_fielded_textbox (textbox, 0); r = 0; } } scrollbar->firstline = (double) 65535.0 *(textbox->firstcolumn * FONT_MEAN_WIDTH) / textbox->column; scrollbar->numlines = (double) 65535.0 *(textbox->width - 6) / textbox->column;}void edit_translate_xy (int xs, int ys, int *x, int *y);void selection_clear (void);static long current;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 (CWidget * w, int x, int y){ long q; y = (y + w->firstline - 1) << 16; if (y < 0) x = y = 0; if (w->options & TEXTBOX_MARK_WHOLE_LINES) x = 0; calc_text_pos_fielded_textbox (w, y, &q, --x); return q;}/* return 1 if not marked */static int marks (CWidget * w, long *start, long *end){ if (w->mark1 == w->mark2) return 1; *start = min (w->mark1, w->mark2); *end = max (w->mark1, w->mark2); return 0;}extern int range (CWidget * w, long start, long end, int click);static void move_mark (CWidget * w){ w->mark2 = w->mark1 = current;}static void fin_mark (CWidget * w){ w->mark2 = w->mark1 = -1;}static void release_mark (CWidget * w, XEvent * event){ w->mark2 = current; if (w->mark2 != w->mark1 && event) { selection_clear (); XSetSelectionOwner (CDisplay, XA_PRIMARY, w->winid, event->xbutton.time); }}/* result must be free'd */static char *get_block (CWidget * w, long start_mark, long end_mark, int *type, int *l){ POOL *p; int tagged, i; unsigned char c, *t; long x, y, a, b; void *data; CPushFont ("editor", 0); a = min (w->mark2, w->mark1); b = max (w->mark2, w->mark1); x = a & 0xFFFFL; y = a >> 16; p = pool_init (); for (;; y++) { unsigned char *text; if (y < w->numlines) data = w->hook; else data = 0; text = compose_line_cached (data, y, w->tab, w->get_line, &tagged); for (;; x++) { if (y == (b >> 16)) if (x >= (b & 0xFFFFL)) goto done; c = text[x]; if (!c) { c = '\n'; pool_write (p, (unsigned char *) &c, 1); break; } if (c == '\f') { int j;#ifdef HAVE_DND if (w->options & TEXTBOX_FILE_LIST) { /* this is a filelist, so only get the first field: i.e. the file name */#else if (*type == DndFiles || *type == DndFile) { /* this is a filelist, so only get the first field: i.e. the file name */#endif c = '\n'; pool_write (p, (unsigned char *) "\n", 1); break; } j = text[++x]; while ((j -= FONT_PER_CHAR(' ')) > 0) pool_write (p, (unsigned char *) " ", 1); pool_write (p, (unsigned char *) " ", 1); continue; } if (c == '\v') { int j; j = pixmap_width (text[++x]); while ((j -= FONT_PER_CHAR(' ')) > 0) pool_write (p, (unsigned char *) " ", 1); continue; } if (this_is_printable (c)) pool_write (p, (unsigned char *) &c, 1); } x = 0; } done: CPopFont ();#ifdef HAVE_DND *type = DndText;#endif *l = pool_length (p); pool_null (p);#ifdef HAVE_DND if (!(w->options & TEXTBOX_FILE_LIST))#else if (!(*type == DndFiles || *type == DndFile))#endif return (char *) pool_break (p); t = (unsigned char *) CDndFileList ((char *) pool_start (p), l, &i); pool_free (p); if (i == 1) *type = DndFile; else *type = DndFiles; return (char *) t;}static void move (CWidget * w, long click, int row){ int h; current = click; if (w->mark2 == -1) w->mark1 = current; h = (w->height - BDR) / FONT_PIX_PER_LINE; if (row > h && w->firstline < w->numlines - h - 2) CSetTextboxPos (w, TEXT_SET_LINE, w->firstline + row - h); if (row < 1) CSetTextboxPos (w, TEXT_SET_LINE, w->firstline + row - 1); w->mark2 = click;}static void motion (CWidget * w, long click){ w->mark2 = click;}struct mouse_funcs fielded_mouse_funcs = { 0, (void (*)(int, int, int *, int *)) xy,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -