"Fossies" - the Fresh Open Source Software archive 
Member "cooledit-3.17.17/widget/fieldedtextbox.c" of archive cooledit-3.17.17.tar.gz:
/* 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) 0
int 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 + 1) * sizeof (int));
memcpy (result, tab, max_num_fields * sizeof (int));
result[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,
(long (*)(void *, int, int)) cp,
(int (*)(void *, long *, long *)) marks,
(int (*)(void *, long, long, long)) range,
(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,
(void (*)(void *, long)) motion,
0,
0,
0,
0,
DndFile
};
CWidget *CDrawFieldedTextbox (const char *identifier, Window parent, int x, int y,
int width, int height, int line, int column,
char **(*get_line) (void *, int, int *, int *),
long options, void *data)
{
char *scroll;
int numlines;
CWidget *wdt;
int *tab, wf;
int w, h, x_hint, y_hint;
CPushFont ("editor", 0);
tab = get_field_sizes (data, &numlines, &wf, get_line);
if (width == AUTO_WIDTH)
w = wf + 6;
else
w = width;
if (height == AUTO_HEIGHT)
h = (max (1, numlines)) * FONT_PIX_PER_LINE + 6;
else
h = height;
wdt = CSetupWidget (identifier, parent, x, y,
w, h, C_FIELDED_TEXTBOX_WIDGET, INPUT_KEY,
color_palette (option_text_bg_normal), 1);
xdnd_set_type_list (CDndClass, wdt->winid, xdnd_typelist_send[DndText]);
wdt->eh = eh_fielded_textbox;
wdt->options = options | WIDGET_TAKES_SELECTION;
wdt->firstline = line;
wdt->firstcolumn = column;
wdt->column = wf;
wdt->cursor = 0;
wdt->numlines = numlines;
wdt->tab = tab;
wdt->get_line = get_line;
wdt->hook = data;
wdt->funcs = mouse_funcs_new (wdt, &fielded_mouse_funcs);
if (h > 80 && height != AUTO_HEIGHT) {
wdt->vert_scrollbar = CDrawVerticalScrollbar (scroll = catstrs (identifier, ".vsc", NULL), parent,
x + w + WIDGET_SPACING, y, h, AUTO_WIDTH, 0, 0);
CSetScrollbarCallback (wdt->vert_scrollbar->ident, wdt->ident, link_scrollbar_to_fielded_textbox);
CGetHintPos (&x_hint, 0);
} else {
x_hint = x + w + WIDGET_SPACING;
}
if (w > 80 && width != AUTO_WIDTH) {
wdt->hori_scrollbar = CDrawHorizontalScrollbar (scroll = catstrs (identifier, ".hsc", NULL), parent,
x, y + h + WIDGET_SPACING, w, (*look->get_fielded_textbox_hscrollbar_width) (), 0, 65535);
CSetScrollbarCallback (wdt->hori_scrollbar->ident, wdt->ident, link_h_scrollbar_to_fielded_textbox);
CGetHintPos (0, &y_hint);
} else {
y_hint = y + h + WIDGET_SPACING;
}
set_hint_pos (x_hint, y_hint);
CPopFont ();
return wdt;
}
CWidget *CRedrawFieldedTextbox (const char *identifier, int preserve)
{
int numlines;
CWidget *wdt;
int *tab, w;
CPushFont ("editor", 0);
wdt = CIdent (identifier);
tab = get_field_sizes (wdt->hook, &numlines, &w, wdt->get_line);
if (!preserve) {
wdt->firstline = 0;
wdt->firstcolumn = 0;
wdt->cursor = 0;
}
wdt->column = w;
wdt->numlines = numlines;
if (wdt->tab)
free (wdt->tab);
wdt->tab = tab;
wdt->mark1 = wdt->mark2 = -1;
CSetColor (color_palette (option_text_bg_normal));
CRectangle (wdt->winid, 3, 3, wdt->width - 3 - 1, wdt->height - 3 - 1);
CExpose (identifier);
CPopFont ();
return wdt;
}
static int calc_text_pos_fielded_textbox (CWidget *w, long b, long *q, int l)
{
int x = 0, c, xn = 0, tagged;
unsigned char *text;
long k;
void *data = 0;
if ((b >> 16) < w->numlines)
data = w->hook;
text = compose_line_cached (data, b >> 16, w->tab, w->get_line, &tagged);
k = b & 0xFFFFL;
if (k == 0xFFFFL)
k = 0;
for (;;) {
c = text[k];
switch (c) {
case '\0':
case '\n':
*q = b;
return x;
case '\f':
xn = x + text[k + 1];
if (xn > l) {
*q = b;
return x;
break;
}
k++;
b++;
break;
case '\b':
case '\r':
xn = x + FONT_PER_CHAR(text[k + 1]);
if (xn > l) {
*q = b;
return x;
break;
}
k++;
b++;
break;
case '\v':
xn = x + pixmap_width (text[k + 1]);
if (xn > l) {
*q = b;
return x;
break;
}
k++;
b++;
break;
default:
xn = x + FONT_PER_CHAR(c);
break;
}
if (xn > l)
break;
x = xn;
b++;
k++;
}
*q = b;
return x;
}
extern int highlight_this_line;
/* here upper 16 bits of q are the line, lowe 16, the column */
static void convert_text_fielded_textbox (CWidget * w, long q, cache_type *line, int x, int x_max, int row)
{
unsigned char *text;
int c, tagged, bold = 0, italic = 0;
cache_type *p;
long m1, m2, k;
void *data = 0;
m1 = min (w->mark1, w->mark2);
m2 = max (w->mark1, w->mark2);
if ((q >> 16) < w->numlines)
data = w->hook;
text = compose_line_cached (data, q >> 16, w->tab, w->get_line, &tagged);
k = q & 0xFFFFL;
if (k == 0xFFFFL)
k = 0;
p = line;
p->c.ch = p->_style = 0;
for (;;) {
c = text[k];
p[1]._style = p[1].c.ch = 0;
p->c.fg = p->c.bg = 0xFF; /* default background colors */
if (highlight_this_line)
p->c.style |= MOD_HIGHLIGHTED;
if (tagged)
p->c.style |= MOD_INVERSE;
if (q >= m1 && q < m2)
p->c.style |= MOD_MARKED;
switch (c) {
case '\0':
case '\n':
(p++)->c.ch = ' ';
if (highlight_this_line || tagged) {
q--;
k--;
x += FONT_PER_CHAR(' ');
} else
return;
break;
case '\f':
k++;
q++;
p->c.style |= MOD_TAB;
(p++)->c.ch = text[k];
x += text[k];
break;
case '\b':
bold = 2;
break;
case '\r':
italic = 2;
break;
case '\v':
k++;
q++;
p->c.style |= MOD_TAB;
(p++)->c.ch = text[k];
x += pixmap_width (text[k]);
break;
default:
x += FONT_PER_CHAR(c);
p->c.ch = c;
if (italic > 0)
p->c.style |= MOD_ITALIC;
if (bold > 0)
p->c.style |= MOD_BOLD;
p++;
break;
}
italic--;
bold--;
if (x > x_max)
break;
q++;
k++;
}
p->c.ch = p->_style = 0;
}
static void fielded_text_print_line (CWidget * w, long b, int row)
{
edit_draw_proportional (w,
(void (*)(void *, long, cache_type *, int, int, int)) convert_text_fielded_textbox,
(int (*)(void *, long, long *, int)) calc_text_pos_fielded_textbox,
-w->firstcolumn * FONT_MEAN_WIDTH, w->winid,
w->width, b, row, row * FONT_PIX_PER_LINE + EDIT_TEXT_VERTICAL_OFFSET, 0,
1);
}
/*
->firstline is line number of the top line in the window.
->firstcolumn is column shift (positive).
->current is actual char position of first line in display.
->numlines is the total number of lines.
->cursor is the number of the highlighted line.
->textlength is the length of text excluding trailing NULL.
First three must be initialised to proper values (e.g. 0, 0 and 0).
*/
extern int EditExposeRedraw;
extern int EditClear;
extern unsigned long edit_normal_background_color;
void render_fielded_textbox (CWidget * w, int redrawall)
{
int row, height, isfocussed, curs, i, x;
static Window last_win = 0;
static int last_firstcolumn = 0;
CPushFont ("editor", 0);
if (redrawall) {
EditExposeRedraw = 1;
EditClear = 1;
}
if (last_win == w->winid && last_firstcolumn != w->firstcolumn) {
x = 0;
CSetColor (color_palette (option_text_bg_normal));
for (i = 0;; i++) {
x += w->tab[i];
if (x >= w->column)
break;
CLine (w->winid, x + LINE_OFFSET - (last_firstcolumn * FONT_MEAN_WIDTH), 3, x + LINE_OFFSET - (last_firstcolumn * FONT_MEAN_WIDTH), (w->numlines - w->firstline) * FONT_PIX_PER_LINE);
}
}
last_firstcolumn = w->firstcolumn;
last_win = w->winid;
height = w->height / FONT_PIX_PER_LINE;
isfocussed = (w->winid == CGetFocus ());
curs = !(w->options & TEXTBOX_NO_CURSOR || w->mark1 != w->mark2); /* don't draw the cursor line */
edit_set_foreground_colors (color_palette (option_text_fg_normal), color_palette (option_text_fg_bold), color_palette (option_text_fg_italic));
edit_set_background_colors (color_palette (option_text_bg_normal), color_palette (0), color_palette (option_text_bg_marked), color_palette (9), color_palette (option_text_bg_highlighted));
for (row = 0; row < height; row++) {
if (row + w->firstline == w->cursor && isfocussed && curs)
highlight_this_line = 1;
else
highlight_this_line = 0;
fielded_text_print_line (w, (row + w->firstline) << 16, row);
}
x = 0;
CSetColor (COLOR_FLAT);
for (i = 0;; i++) {
if (!w->tab[i])
break;
x += w->tab[i];
if (x >= w->column)
break;
CLine (w->winid, x + LINE_OFFSET - (w->firstcolumn * FONT_MEAN_WIDTH), 3, x + LINE_OFFSET - (w->firstcolumn * FONT_MEAN_WIDTH), (w->numlines - w->firstline) * FONT_PIX_PER_LINE + 3);
}
if ((w->numlines - w->firstline) * FONT_PIX_PER_LINE < w->height) {
x = 0;
CSetColor (color_palette (option_text_bg_normal));
for (i = 0;; i++) {
if (!w->tab[i])
break;
x += w->tab[i];
if (x >= w->column)
break;
CLine (w->winid, x + LINE_OFFSET - (w->firstcolumn * FONT_MEAN_WIDTH), (w->numlines - w->firstline) * FONT_PIX_PER_LINE + 3, x + LINE_OFFSET - (w->firstcolumn * FONT_MEAN_WIDTH), w->height - 3);
}
}
EditExposeRedraw = 0;
EditClear = 0;
(*look->render_fielded_textbox_tidbits) (w, isfocussed);
CPopFont ();
return;
}
/*
Count the number of lines that would be printed
by the above routine, but don't print anything.
If all is non-zero then count all the lines.
*/
static long count_fielded_textbox_lines (CWidget * wdt)
{
long height;
height = wdt->height / FONT_PIX_PER_LINE;
if (wdt->numlines - wdt->firstline < height)
return wdt->numlines - wdt->firstline;
return height;
}
static void fielded_text_mouse_mark (CWidget * w, XEvent * event, CEvent * ce)
{
CPushFont ("editor", 0);
mouse_mark (event, ce->double_click, w->funcs);
CPopFont ();
}
/* gets selected text into selection structure, stripping nroff */
void fielded_text_get_selection (CWidget * w)
{
int type;
if (selection.text)
free (selection.text);
selection.text = (unsigned char *) get_block (w, 0, 0, &type, &selection.len);
}
void selection_send (XSelectionRequestEvent * rq);
int eh_fielded_textbox (CWidget * w, XEvent * xevent, CEvent * cwevent)
{
int handled = 0, redrawall = 0, count;
switch (xevent->type) {
case SelectionRequest:
fielded_text_get_selection (w);
selection_send (&(xevent->xselectionrequest));
return 1;
case Expose:
if (!xevent->xexpose.count)
redrawall = 1;
break;
case ClientMessage:
w->mark1 = w->mark2 = 0;
break;
case ButtonPress:
CPushFont ("editor", 0);
CFocus (w);
if (xevent->xbutton.button == Button1)
w->cursor = (xevent->xbutton.y - BDR) / FONT_PIX_PER_LINE + w->firstline;
if (w->cursor > w->numlines - 1)
w->cursor = w->numlines - 1;
if (w->cursor < 0)
w->cursor = 0;
cwevent->ident = w->ident;
cwevent->xt = (xevent->xbutton.x - 7) / FONT_MEAN_WIDTH + w->firstcolumn;
cwevent->yt = w->cursor;
CPopFont ();
case ButtonRelease:
case MotionNotify:
if (!xevent->xmotion.state && xevent->type == MotionNotify)
return 0;
resolve_button (xevent, cwevent);
fielded_text_mouse_mark (w, xevent, cwevent);
break;
case FocusIn:
case FocusOut:
break;
case KeyPress:
cwevent->ident = w->ident;
if (!(TEXTBOX_NO_KEYS & w->options)) {
if (w->options & TEXTBOX_FILE_LIST && w->hook) {
if (cwevent->key == XK_Insert || cwevent->key == XK_KP_Insert) {
if (w->mark1 == w->mark2) {
struct file_entry *f;
f = (struct file_entry *) w->hook;
if (f[w->cursor].options & FILELIST_TAGGED_ENTRY)
f[w->cursor].options &= (0xFFFFFFFFUL - FILELIST_TAGGED_ENTRY);
else
f[w->cursor].options |= FILELIST_TAGGED_ENTRY;
CTextboxCursorMove (w, CK_Down);
handled = 1;
break;
}
}
}
handled = CTextboxCursorMove (w, cwevent->command);
}
break;
default:
return 0;
}
/* Now draw the changed text box, count will contain
the number of textlines displayed */
render_fielded_textbox (w, redrawall);
count = count_fielded_textbox_lines (w);
/* now update the scrollbar position */
if (w->vert_scrollbar && w->numlines) {
w->vert_scrollbar->firstline = (double) 65535.0 *w->firstline / (w->numlines ? w->numlines : 1);
w->vert_scrollbar->numlines = (double) 65535.0 *count / (w->numlines ? w->numlines : 1);
w->vert_scrollbar->options = 0;
render_scrollbar (w->vert_scrollbar);
}
if (w->hori_scrollbar && w->column) {
w->hori_scrollbar->firstline = (double) 65535.0 *(w->firstcolumn * FONT_MEAN_WIDTH) / w->column;
w->hori_scrollbar->numlines = (double) 65535.0 *(w->width - 6) / w->column;
w->hori_scrollbar->options = 0;
render_scrollbar (w->hori_scrollbar);
}
return handled;
}