1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
/* Tk Viewer stuff.
Copyright (C) 1995 Miguel de Icaza
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.
-----
This module is here so that I can learn to shut up my mouth.
I know, Jakub is enjoying this moment, anyways, this code is still
smaller than a complete tkview.c program, and it's just interface
code so that the code knows about the window resize.
*/
#include <stdio.h>
#define WANT_WIDGETS
#include "dlg.h"
#include "view.h"
#include "tkmain.h"
void
x_init_view (WView *view)
{
view->status_shown = 0;
view->current_line = 1;
view->cache_len = 80;
view->last_col = 0;
view->cache = xmalloc (81, "view->cache");
view->color_cache = xmalloc (81, "view->cache");
view->direction = 1;
bzero (view->cache, 81);
view->dest = 0;
}
void
x_destroy_view (WView *view)
{
free (view->cache);
free (view->color_cache);
}
/* Accepts the dim command with the width and the height in characters */
static int
tk_viewer_callback (ClientData cd, Tcl_Interp *interp, int ac, char *av[])
{
WView *view = (WView *) cd;
if (av [1][0] != 'd')
return TCL_OK;
view->widget.cols = atoi (av [2]);
view->widget.lines = atoi (av [3]);
return TCL_OK;
}
void
x_create_viewer (WView *view)
{
char *cmd;
widget_data parent;
/* First, check if our parent is ".", if this is the case, then
* create a stand alone viewer, otherwise, we create a paneled
* version of the viewer
*/
if (view->have_frame){
parent = view->widget.wcontainer;
} else {
parent = view->widget.parent->wdata;
}
cmd = tk_new_command (parent, view, tk_viewer_callback, 'v');
tk_evalf ("newview %d %s %s %s", view->have_frame,
view->have_frame ? (char *) view->widget.wcontainer : "{}",
cmd+1, cmd);
}
void
x_focus_view (WView *view)
{
tk_evalf ("focus %s.v.view", wtk_win (view->widget));
}
void
view_status (WView *view)
{
char *window = wtk_win (view->widget);
if (!view->status_shown){
view->status_shown = 0;
tk_evalf ("view_update_info %s {%s} {%d} {%s} {%s}",
window, name_trunc (view->filename ? view->filename:
view->command ? view->command:"", 20),
-view->start_col, size_trunc (view->s.st_size),
view->growing_buffer ? "[grow]":"[]");
}
}
void
view_percent (WView *view, int p, int w)
{
fprintf (stderr, "Missing tk view_percent\n");
}
/* The major part of the Tk code deals with caching a line (the
* current one) of text to avoid expensive calls to the Tk text widget
* callback.
*
* We cache all this information on view->cache and the colors on
* view->color_cache.
*
* FIXME: the cache does not know about the contents of the physical
* text widget (depends on your concept of physical), so if we happen
* to hit the case where row is decremented in the void display () routine,
* we will end up with a clean line.
*/
static int current_color;
void
view_set_color (WView *view, int font)
{
current_color = font;
}
void
view_display_clean(WView *view, int h, int w)
{
char *win = wtk_win (view->widget);
tk_evalf ("cleanview %s.v.view", win);
}
void
view_add_character (WView *view, int c)
{
view->cache [view->dest] = c;
view->color_cache [view->dest] = current_color;
}
void
view_add_string (WView *view, char *s)
{
while (*s)
view_add_character (view, *s++);
}
static char *
get_tk_tag_name (int color)
{
/* Those names are the names of the tags in the Tk source */
static char *color_tag_names [] = {
"normal", "bold", "underline", "mark"
};
return color_tag_names [color];
}
/*
* Tk: Flushes the contents of view->cache to the Tk text widget
*
* We get the command information and call the command directly
* to avoid escaping the view->cache contents.
*/
static void
flush_line (WView *view)
{
char *win = wtk_win (view->widget);
int row = view->current_line;
char *text_name;
Tcl_CmdInfo info;
int i, prev_color;
char str_row [30];
char *av [5];
int len = strlen (view->cache);
/* Fetch the address and clientData for the view */
text_name = copy_strings (win, ".v.view", 0);
Tcl_GetCommandInfo (interp, text_name, &info);
/* Setup arguments to the command:
* $win.v.view insert @$row,0 $view->cache
*/
sprintf (str_row, "%d.0", row);
i = 0;
av [i++] = text_name;
av [i++] = "insert";
av [i++] = str_row;
av [i++] = view->cache;
/* Call the callback :-) */
(*info.proc) (info.clientData, interp, i, av);
bzero (view->cache, view->cache_len);
/* Colorize the line */
for (prev_color = 0, i = 0; i < len; i++){
int new_color_start;
char *color_name;
if (view->color_cache [i] == prev_color)
continue;
new_color_start = i;
prev_color = view->color_cache [i];
for (;i < len && view->color_cache [i] == prev_color; i++)
;
color_name = get_tk_tag_name (prev_color);
tk_evalf ("%s tag add %s %d.%d %d.%d",
text_name, color_name,
row, new_color_start-1,
row, i);
}
bzero (view->color_cache, view->cache_len);
view->last_col = 0;
free (text_name);
}
/* Tk: Mantains the line cache */
void
view_gotoyx (WView *view, int row, int col)
{
if (row != view->current_line){
flush_line (view);
}
view->current_line = row;
/* In case the user has resized the viewer */
if (col > view->cache_len){
char *new;
new = xmalloc (col + 1, "cache");
strcpy (new, view->cache);
free (view->cache);
view->cache = new;
new = xmalloc (col + 1, "cache");
strcpy (new, view->color_cache);
free (view->color_cache);
view->color_cache = new;
view->cache_len = col;
}
view->dest = col;
for (; view->last_col+1 < col; view->last_col++){
view->cache [view->last_col] = ' ';
view->color_cache [view->last_col] = current_color;
}
view->last_col = col;
}
|