tkview.c 6.4 KB

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