home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / git-4.3 / git-4 / git-4.3.11 / src / gitview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-06  |  14.7 KB  |  724 lines

  1. /* gitview.c -- A hex/ascii file viewer.  */
  2.  
  3. /* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* Written by Tudor Hulubei and Andrei Pitis.  */
  20.  
  21.  
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25.  
  26. #include <stdio.h>
  27.  
  28. #ifdef HAVE_STDLIB_H
  29. #include <stdlib.h>
  30. #else /* !HAVE_STDLIB_H */
  31. #include "ansi_stdlib.h"
  32. #endif /* !HAVE_STDLIB_H */
  33.  
  34. #include <sys/types.h>
  35. #include <limits.h>
  36. #include "file.h"
  37. #include <signal.h>
  38. #include <ctype.h>
  39.  
  40. #ifdef HAVE_UNISTD_H
  41. #include <unistd.h>
  42. #endif /* HAVE_UNISTD_H */
  43.  
  44. #include "stdc.h"
  45. #include "xstring.h"
  46. #include "xmalloc.h"
  47. #include "xio.h"
  48. #include "window.h"
  49. #include "configure.h"
  50. #include "tty.h"
  51. #include "misc.h"
  52. #include "tilde.h"
  53.  
  54.  
  55. #define MAX_KEYS                        2048
  56.  
  57. #define BUILTIN_OPERATIONS              11
  58.  
  59.  
  60. #define BUILTIN_previous_line           -1
  61. #define BUILTIN_next_line               -2
  62. #define BUILTIN_scroll_down             -3
  63. #define BUILTIN_scroll_up               -4
  64. #define BUILTIN_beginning_of_file       -5
  65. #define BUILTIN_end_of_file             -6
  66. #define BUILTIN_refresh                 -7
  67. #define BUILTIN_exit                    -8
  68. #define BUILTIN_hard_refresh            -9
  69. #define BUILTIN_backspace               -10
  70. #define BUILTIN_action                  -11
  71.  
  72.  
  73. #define MAX_BUILTIN_NAME                20
  74.  
  75. char built_in[BUILTIN_OPERATIONS][MAX_BUILTIN_NAME] =
  76. {
  77.     "previous-line",
  78.     "next-line",
  79.     "scroll-down",
  80.     "scroll-up",
  81.     "beginning-of-file",
  82.     "end-of-file",
  83.     "refresh",
  84.     "exit",
  85.     "hard-refresh",
  86.     "backspace",
  87.     "action",
  88. };
  89.  
  90.  
  91. int SCREEN_X;
  92. int SCREEN_Y;
  93.  
  94. #define VIEWER_FIELDS 12
  95.  
  96. static char *ViewerFields[VIEWER_FIELDS] =
  97. {
  98.     "TitleForeground",
  99.     "TitleBackground",
  100.     "TitleBrightness",
  101.     "HeaderForeground",
  102.     "HeaderBackground",
  103.     "HeaderBrightness",
  104.     "ScreenForeground",
  105.     "ScreenBackground",
  106.     "ScreenBrightness",
  107.     "StatusForeground",
  108.     "StatusBackground",
  109.     "StatusBrightness"
  110. };
  111.  
  112. #ifdef HAVE_LINUX
  113. static int ViewerColors[VIEWER_FIELDS] =
  114. {
  115.     CYAN, BLUE, ON, CYAN, RED, ON, BLACK, CYAN, OFF, CYAN, BLUE, ON
  116. };
  117. #else   /* !HAVE_LINUX */
  118. static int ViewerColors[VIEWER_FIELDS] =
  119. {
  120.     BLACK, WHITE, OFF, WHITE, BLACK, ON, WHITE, BLACK, OFF, BLACK, WHITE, OFF
  121. };
  122. #endif  /* !HAVE_LINUX */
  123.  
  124. #define TitleForeground                 ViewerColors[0]
  125. #define TitleBackground                 ViewerColors[1]
  126. #define TitleBrightness                 ViewerColors[2]
  127. #define HeaderForeground                ViewerColors[3]
  128. #define HeaderBackground                ViewerColors[4]
  129. #define HeaderBrightness                ViewerColors[5]
  130. #define ScreenForeground                ViewerColors[6]
  131. #define ScreenBackground                ViewerColors[7]
  132. #define ScreenBrightness                ViewerColors[8]
  133. #define StatusForeground                ViewerColors[9]
  134. #define StatusBackground                ViewerColors[10]
  135. #define StatusBrightness                ViewerColors[11]
  136.  
  137.  
  138. #ifdef HAVE_LINUX
  139. extern int LinuxConsole;
  140. #endif /* HAVE_LINUX */
  141.  
  142. #ifdef HAVE_LINUX
  143. int AnsiColors = ON;
  144. #else   /* !HAVE_LINUX */
  145. int AnsiColors = OFF;
  146. #endif  /* !HAVE_LINUX */
  147.  
  148.  
  149. #ifdef STAT_MACROS_BROKEN
  150. #ifdef S_IFREG
  151. #undef S_IFREG
  152. #endif
  153. #ifdef S_IFBLK
  154. #undef S_IFBLK
  155. #endif
  156. #endif /* STAT_MACROS_BROKEN */
  157.  
  158.  
  159. #ifndef S_IFREG
  160. #define S_IFREG         0100000
  161. #endif
  162.  
  163. #ifndef S_IFBLK
  164. #define S_IFBLK         0060000
  165. #endif
  166.  
  167. #ifndef S_ISREG
  168. #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
  169. #endif
  170.  
  171. #ifndef S_ISBLK
  172. #define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
  173. #endif
  174.  
  175. /* Finally ... :-( */
  176.  
  177.  
  178. char *home;
  179. pid_t pid;
  180. char *program;
  181. char *tty_name;
  182. size_t tty_name_len;
  183. char *screen;
  184. char *header_text;
  185. int  UseLastScreenChar;
  186. char *global_buf = NULL;
  187. char cSection[]  = "[GITVIEW-Color]";
  188. char bwSection[] = "[GITVIEW-Monochrome]";
  189. int handle, regular_file;
  190. int current_line, lines;
  191. window_t *title_win, *header_win, *screen_win, *status_win;
  192. #ifdef HAVE_GCC
  193. static char title_text[] = " "PRODUCT" "VERSION" - Hex/Ascii File Viewer";
  194. #else
  195. static char title_text[] = " GNU Interactive Tools 4.3.11 - Hex/Ascii File Viewer";
  196. #endif /* !HAVE_GCC */
  197. static char *GitViewModeHelp;
  198. static char info_txt[] =
  199.     "   Offset    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        \
  200. Ascii       ";
  201. static char line_txt[]    =
  202.     "  ------------------------------------------------------------------\
  203. ----------  ";
  204. static char seek_txt[]    = "  Seek at: ";
  205.  
  206.  
  207. int
  208. file_length()
  209. {
  210.     int tmp, length;
  211.  
  212.     if (!regular_file)
  213.     return 0x7FFFFFFF;
  214.  
  215.     tmp    = lseek(handle, 0, SEEK_CUR);
  216.     length = lseek(handle, 0, SEEK_END);
  217.     lseek(handle, tmp, SEEK_SET);
  218.     return length;
  219. }
  220.  
  221.  
  222. void
  223. settitle()
  224. {
  225.     memset(global_buf, ' ', SCREEN_X);
  226.     memcpy(global_buf, title_text, strlen(title_text));
  227.  
  228.     tty_colors(TitleBrightness, TitleForeground, TitleBackground);
  229.  
  230.     window_goto(title_win, 0, 0);
  231.     window_puts(global_buf, SCREEN_X);
  232. }
  233.  
  234.  
  235. void
  236. setheader()
  237. {
  238.     memset(global_buf, ' ', SCREEN_X);
  239.     memcpy(global_buf, header_text, min(strlen(header_text), SCREEN_X));
  240.  
  241.     tty_colors(HeaderBrightness, HeaderForeground, HeaderBackground);
  242.  
  243.     window_goto(header_win, 0, 0);
  244.     window_puts(global_buf, SCREEN_X);
  245. }
  246.  
  247.  
  248. void
  249. setstatus()
  250. {
  251.     memset(global_buf, ' ', SCREEN_X);
  252.     memcpy(global_buf, GitViewModeHelp, strlen(GitViewModeHelp));
  253.  
  254.     tty_colors(StatusBrightness, StatusForeground, StatusBackground);
  255.  
  256.     window_goto(status_win, 0, 0);
  257.  
  258.     if (UseLastScreenChar)
  259.     window_puts(global_buf, SCREEN_X);
  260.     else
  261.     window_puts(global_buf, SCREEN_X - 1);
  262. }
  263.  
  264.  
  265. char
  266. char_to_print(c)
  267.     char c;
  268. {
  269.     return is_print(c) ? c : '.';
  270. }
  271.  
  272.  
  273. void
  274. update_line(line)
  275.     int line;
  276. {
  277.     int r;
  278.     unsigned char ln[16];
  279.  
  280.     memset(ln, 0, 16);
  281.     memset(global_buf, ' ', SCREEN_X);
  282.     lseek(handle, line * 16, SEEK_SET);
  283.  
  284.     if ((r = read(handle, ln, 16)))
  285.     sprintf(global_buf, "  %07X0   %02X %02X %02X %02X %02X %02X %02X\
  286.  %02X %02X %02X %02X %02X %02X %02X %02X %02X  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c  ",
  287.         line,
  288.         ln[0], ln[1], ln[2],  ln[3],  ln[4],  ln[5],  ln[6],  ln[7],
  289.         ln[8], ln[9], ln[10], ln[11], ln[12], ln[13], ln[14], ln[15],
  290.         char_to_print(ln[0]),  char_to_print(ln[1]),
  291.         char_to_print(ln[2]),  char_to_print(ln[3]),
  292.         char_to_print(ln[4]),  char_to_print(ln[5]),
  293.         char_to_print(ln[6]),  char_to_print(ln[7]),
  294.         char_to_print(ln[8]),  char_to_print(ln[9]),
  295.         char_to_print(ln[10]), char_to_print(ln[11]),
  296.         char_to_print(ln[12]), char_to_print(ln[13]),
  297.         char_to_print(ln[14]), char_to_print(ln[15]));
  298.  
  299.     if (r < 0)
  300.     r = 0;
  301.  
  302.     if (r != 16)
  303.     {
  304.     memset(global_buf + 13 + r * 3, ' ', (16 - r) * 3 - 1);
  305.     memset(global_buf + 13 + 16 * 3 - 1 + 2 + r, ' ', 16 - r + 2);
  306.     }
  307.  
  308.     window_puts((char *)global_buf, SCREEN_X);
  309. }
  310.  
  311.  
  312. void
  313. update_all()
  314. {
  315.     int i;
  316.  
  317.     tty_colors(ScreenBrightness, ScreenForeground, ScreenBackground);
  318.  
  319.     for (i = current_line; i < current_line + 16; i++)
  320.     {
  321.     window_goto(screen_win, 3 + i - current_line, 0);
  322.     update_line(i);
  323.     }
  324. }
  325.  
  326.  
  327. void
  328. clean_up()
  329. {
  330.     tty_exit(NULL);
  331. }
  332.  
  333.  
  334. void
  335. fatal(postmsg)
  336.     char *postmsg;
  337. {
  338.     clean_up();
  339.     fprintf(stderr, "%s: fatal error: %s.\n", program, postmsg);
  340.     exit(1);
  341. }
  342.  
  343.  
  344. RETSIGTYPE
  345. panic(signum)
  346.     int signum;
  347. {
  348.     fatal_signal(signum);
  349. }
  350.  
  351.  
  352. int
  353. read_keys(keys)
  354.     int keys;
  355. {
  356.     char *contents;
  357.     char key_seq[80];
  358.     int i, j, need_convertion;
  359.  
  360.  
  361.     for (i = keys; i < MAX_KEYS; i++)
  362.     {
  363.     configuration_getvarinfo(key_seq, &contents, 1, NO_SEEK);
  364.  
  365.     if (*key_seq == 0)
  366.         break;
  367.  
  368.     if (*key_seq != '^')
  369.     {
  370.         char *key_seq_ptr = tty_get_symbol_key_seq(key_seq);
  371.  
  372.         if (!(need_convertion = key_seq_ptr == NULL))
  373.         strcpy(key_seq, key_seq_ptr);
  374.     }
  375.     else
  376.         need_convertion = 1;
  377.  
  378.     if (contents == NULL) continue;
  379.  
  380.     for (j = 0; j < BUILTIN_OPERATIONS; j++)
  381.         if (strcmp(contents, built_in[j]) == 0)
  382.         break;
  383.  
  384.     if (j < BUILTIN_OPERATIONS)
  385.     {
  386.         if (!need_convertion || tty_key_convert((unsigned char *)key_seq))
  387.         tty_key_list_insert((unsigned char *)key_seq,
  388.                     (void *)(int)-(j + 1));
  389.     }
  390.     else
  391.         fprintf(stderr, "%s: invalid built-in operation: %s.\n",
  392.             program, contents);
  393.     }
  394.  
  395.     return i;
  396. }
  397.  
  398.  
  399. int
  400. main(argc, argv)
  401.     int argc;
  402.     char *argv[];
  403. {
  404.     char c;
  405.     struct stat s;
  406.     tty_key_t *ks;
  407.     char offset[16];
  408.     int cnt = 0, size;
  409.     int key, first_time = 1;
  410.     int keys, repeat_count, need_update;
  411.  
  412.  
  413.     program = argv[0];
  414.  
  415.     home = getenv("HOME");
  416.     if (home == NULL)
  417.     home = ".";
  418.  
  419.     get_tty_name();
  420.     get_login_name();
  421.  
  422.     tty_name_len = strlen(tty_name);
  423.  
  424.     tty_get_capabilities();
  425.     tty_kbdinit(TTY_RESTRICTED_INPUT);
  426.  
  427.     signal(SIGTERM, panic);
  428.     signal(SIGINT , panic);
  429.     signal(SIGQUIT, panic);
  430.     signal(SIGSEGV, panic);
  431.     signal(SIGHUP,  panic);
  432.  
  433.     signal(SIGILL,  SIG_IGN);
  434.     signal(SIGTRAP, SIG_IGN);
  435.     signal(SIGABRT, SIG_IGN);
  436.     signal(SIGUSR1, SIG_IGN);
  437.     signal(SIGUSR2, SIG_IGN);
  438.  
  439. #ifdef SIGTSTP
  440.     signal(SIGTSTP, SIG_IGN);
  441. #endif
  442.  
  443. #ifdef SIGCONT
  444.     signal(SIGCONT, SIG_IGN);
  445. #endif
  446.  
  447.     signal(SIGALRM, SIG_IGN);
  448.     signal(SIGPIPE, SIG_IGN);
  449.     signal(SIGFPE,  SIG_IGN);
  450.  
  451.     if (argc != 2)
  452.     {
  453.     fprintf(stderr, "usage: gitview filename\n");
  454.     exit(1);
  455.     }
  456.  
  457.     xstat(argv[1], &s);
  458.  
  459. /*
  460.     if (!(S_ISREG(s.st_mode) || S_ISBLK(s.st_mode)))
  461.     {
  462.     fprintf(stderr, "%s: %s is neither regular file nor block device.\n",
  463.         program, argv[1]);
  464.     exit(1);
  465.     }
  466. */
  467.     handle = open(argv[1], O_RDONLY);
  468.  
  469.     if (handle == -1)
  470.     {
  471.     fprintf(stderr, "%s: cannot open file %s.\n", program, argv[1]);
  472.     exit(1);
  473.     }
  474.  
  475.     regular_file = S_ISREG(s.st_mode);
  476.  
  477.     common_configuration_init();
  478.     use_section("[GITVIEW-Keys]");
  479.     keys = read_keys(0);
  480.     configuration_end();
  481.  
  482.     specific_configuration_init();
  483.  
  484.     use_section("[Setup]");
  485.  
  486.     AnsiColors         = get_flag_var("AnsiColors", OFF);
  487.     UseLastScreenChar  = get_flag_var("UseLastScreenChar", OFF);
  488.  
  489.  
  490.     use_section("[GITVIEW-Setup]");
  491.  
  492.     GitViewModeHelp = get_string_var("GitViewModeHelp", "");
  493.  
  494.     use_section(AnsiColors ? cSection : bwSection);
  495.  
  496.     get_colorset_var(ViewerColors, ViewerFields, VIEWER_FIELDS);
  497.  
  498.  
  499.     use_section("[GITVIEW-Keys]");
  500.  
  501.     keys = read_keys(keys);
  502.  
  503.     if (keys == MAX_KEYS)
  504.     fprintf(stderr, "%s: too many key sequences; only %d are allowed.\n",
  505.         program, MAX_KEYS);
  506.  
  507.     configuration_end();
  508.  
  509.     tty_get_size(&SCREEN_X, &SCREEN_Y);
  510.     tty_startup(UseLastScreenChar);
  511.  
  512.     if (SCREEN_Y < 24)
  513.     {
  514.     SCREEN_Y = 24;
  515.     fprintf(stderr, "%s: WARNING: can't use less than 24 columns.\n",
  516.         program);
  517.     }
  518.  
  519. #ifdef HAVE_LINUX
  520.     if (LinuxConsole)
  521.     screen = xmalloc(4 + SCREEN_X * SCREEN_Y * 2);
  522. #endif  /* HAVE_LINUX */
  523.  
  524.     global_buf  = xmalloc(SCREEN_X + 1);
  525.  
  526.     header_text = xmalloc(strlen(argv[1]) + 10);
  527.     sprintf(header_text, " File: %s", argv[1]);
  528.  
  529.     title_win  = window_init(0, 0,            1,            SCREEN_X);
  530.     header_win = window_init(0, 1,            1,            SCREEN_X);
  531.     screen_win = window_init(0, 2,            SCREEN_Y - 2, SCREEN_X);
  532.     status_win = window_init(0, SCREEN_Y - 1, 1,            SCREEN_X);
  533.  
  534.     tty_get_screen(screen);
  535.     tty_set_mode(TTY_NONCANONIC);
  536.     tty_defaults();
  537.  
  538.     offset[cnt]  = 0;
  539.     current_line = 0;
  540.  
  541.  
  542. restart:
  543.  
  544.     tty_colors(ScreenBrightness, ScreenForeground, ScreenBackground);
  545.  
  546.     if (first_time)
  547.     {
  548.     tty_fill();
  549.     first_time = 0;
  550.     }
  551.  
  552.     settitle();
  553.     setstatus();
  554.     setheader();
  555.  
  556.     tty_colors(ScreenBrightness, ScreenForeground, ScreenBackground);
  557.  
  558.     window_goto(screen_win, 1, 0);
  559.     window_puts(info_txt, sizeof(info_txt) - 1);
  560.     window_goto(screen_win, 2, 0);
  561.     window_puts(line_txt, sizeof(line_txt) - 1);
  562.  
  563.     size = file_length();
  564.     lines = size / 16 + (size % 16 ? 1 : 0);
  565.  
  566.     current_line = min(current_line, (lines / 16) * 16);
  567.  
  568.     update_all();
  569.  
  570.     window_goto(screen_win, 20, 0);
  571.     window_puts(seek_txt, sizeof(seek_txt) - 1);
  572.     window_goto(screen_win, 20, sizeof(seek_txt) - 1);
  573.     window_puts(offset, cnt);
  574.  
  575.     window_goto(screen_win, 20, sizeof(seek_txt) - 1 + cnt);
  576.  
  577.     while (1)
  578.     {
  579.     ks  = tty_get_key(&repeat_count);
  580.     key = (int)ks->aux_data;
  581.  
  582.     if (key == 0)
  583.         key = ks->key_seq[0];
  584.  
  585.     size = file_length();
  586.     lines = size / 16 + (size % 16 ? 1 : 0);
  587.  
  588.     switch (key)
  589.     {
  590.         case key_INTERRUPT:
  591.         goto end;
  592.  
  593.         case BUILTIN_previous_line:
  594.  
  595.         need_update = 0;
  596.  
  597.         while (repeat_count--)
  598.         {
  599.             if (current_line == 0)
  600.             break;
  601.             current_line--, need_update = 1;
  602.         }
  603.  
  604.         if (need_update)
  605.             update_all();
  606.         break;
  607.  
  608.         case BUILTIN_next_line:
  609.  
  610.         need_update = 0;
  611.  
  612.         while (repeat_count--)
  613.         {
  614.             if (current_line >= lines - 16)
  615.             break;
  616.             current_line++, need_update = 1;
  617.         }
  618.  
  619.         if (need_update)
  620.             update_all();
  621.         break;
  622.  
  623.         case BUILTIN_scroll_down:
  624.  
  625.         if (current_line == 0)
  626.             break;
  627.  
  628.         current_line = max(0, current_line - 16);
  629.         update_all();
  630.         break;
  631.  
  632.         case BUILTIN_scroll_up:
  633.  
  634.         if (current_line >= lines - 16)
  635.             break;
  636.  
  637.         current_line += 16;
  638.         update_all();
  639.         break;
  640.  
  641.         case BUILTIN_beginning_of_file:
  642.  
  643.         if (current_line)
  644.         {
  645.             current_line = 0;
  646.             update_all();
  647.         }
  648.         break;
  649.  
  650.         case BUILTIN_end_of_file:
  651.  
  652.         if (regular_file && current_line < lines - 16)
  653.         {
  654.             current_line = lines - 16;
  655.             update_all();
  656.         }
  657.         break;
  658.  
  659.         case BUILTIN_hard_refresh:
  660.  
  661.         first_time = 1;
  662.  
  663.         case BUILTIN_refresh:
  664.  
  665.         goto restart;
  666.  
  667.         case '0': case '1': case '2': case '3': case '4': case '5':
  668.         case '6': case '7': case '8': case '9': case 'A': case 'B':
  669.         case 'C': case 'D': case 'E': case 'F': case 'a': case 'b':
  670.         case 'c': case 'd': case 'e': case 'f':
  671.         if (cnt < 8)
  672.         {
  673.             window_goto(screen_win, 20, strlen(seek_txt) + cnt);
  674.             c = (char)key;
  675.             window_putc(c);
  676.             offset[cnt++] = c;
  677.         }
  678.         else
  679.             tty_beep();
  680.         break;
  681.  
  682.         case BUILTIN_backspace:
  683.  
  684.         if (cnt)
  685.             cnt--;
  686.  
  687.         window_goto(screen_win, 20, strlen(seek_txt) + cnt);
  688.         window_putc(' ');
  689.         break;
  690.  
  691.         case BUILTIN_action:
  692.  
  693.         if (cnt == 0)
  694.             tty_beep();
  695.         else
  696.         {
  697.             offset[cnt] = 0;
  698.             sscanf(offset, "%x", &cnt);
  699.             window_goto(screen_win, 20, strlen(seek_txt));
  700.             window_puts("        ", 8);
  701.             if (cnt < 0)    cnt = 0;
  702.             if (cnt > size) cnt = size;
  703.             current_line = cnt >> 4;
  704.             update_all();
  705.             cnt = 0;
  706.         }
  707.         break;
  708.  
  709.         case BUILTIN_exit:
  710.         goto end;
  711.  
  712.         default:
  713.         break;
  714.     }
  715.  
  716.     window_goto(screen_win, 20, strlen(seek_txt) + cnt);
  717.     }
  718.  
  719.   end:
  720.  
  721.     tty_exit(screen);
  722.     return 0;
  723. }
  724.