home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / lumberjack / ljack.c next >
C/C++ Source or Header  |  1988-11-14  |  6KB  |  305 lines

  1. #include <stdio.h>
  2. #include <values.h>
  3. #include <signal.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <sys/file.h>
  7. #include <sys/time.h>
  8. #include <suntool/sunview.h>
  9. #include <suntool/frame.h>
  10. #include <suntool/textsw.h>
  11. #include <sunwindow/notify.h>
  12.  
  13. /*
  14.  * SunView size definitions.  I shouldn't have to define these, but
  15.  * there is no way to query SunView for them.
  16.  */
  17. #define LMARGIN        5    /* left frame margin */
  18. #define RMARGIN        5    /* right frame margin */
  19. #define BMARGIN        5    /* bottom frame margin */
  20. #define SMARGIN        5    /* subwindow spacing */
  21.  
  22. Frame    frame;
  23. int    files, updating = 0;
  24. Textsw    text[16];        /* text subwindows */
  25. Menu    menu[16];        /* menus for each subwindow */
  26. char    *file[16];        /* filenames */
  27. off_t    length[16];        /* file lengths */
  28. char    alert[16];        /* flags: blink icon on update? */
  29.  
  30. /*
  31.  * Construct the icons.
  32.  * None.icon is displayed when there are no new files; otherwise,
  33.  * new1.icon and new2.icon are toggled once a second.
  34.  */
  35. static short none_icon_i[] = {
  36. #include "none.icon"
  37. };
  38. mpr_static(none_icon_p, 64, 64, 1, none_icon_i);
  39.  
  40. static short new1_icon_i[] = {
  41. #include "new1.icon"
  42. };
  43. mpr_static(new1_icon_p, 64, 64, 1, new1_icon_i);
  44.  
  45. static short new2_icon_i[] = {
  46. #include "new2.icon"
  47. };
  48. mpr_static(new2_icon_p, 64, 64, 1, new2_icon_i);
  49.  
  50. Icon ikes[3];
  51. int  inum = 1;
  52. int  newstuff;
  53.  
  54. main(argc, argv)
  55. char **argv;
  56. {
  57.     ikes[0] = icon_create(ICON_IMAGE, &none_icon_p, 0);
  58.     ikes[1] = icon_create(ICON_IMAGE, &new1_icon_p, 0);
  59.     ikes[2] = icon_create(ICON_IMAGE, &new2_icon_p, 0);
  60.  
  61.     frame = window_create(NULL, FRAME,
  62.         FRAME_LABEL,        "LUMBERJACK 1.0 by Steven Grimm (koreth@ssyx.ucsc.edu)",
  63.         FRAME_ARGC_PTR_ARGV,    &argc, argv,
  64.         FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
  65.         FRAME_ICON,        ikes[0],
  66.         WIN_ERROR_MSG,        "Couldn't open window",
  67.         0);
  68.  
  69.     parse_args(argc, argv);
  70.     create_subwindows();
  71.     set_window_sizes();
  72.     load_files();
  73.  
  74.     newstuff = 0;
  75.     window_set(frame, FRAME_ICON, ikes[0], 0);
  76.  
  77.     set_notifier();
  78.  
  79.     window_main_loop(frame);
  80. }
  81.  
  82. /*
  83.  * Create all the necessary subwindows.
  84.  */
  85. create_subwindows()
  86. {
  87.     int i, domenu();
  88.  
  89.     for (i=0; i<files; i++)
  90.     {
  91.         menu[i] = menu_create(MENU_TITLE_ITEM, file[i],
  92.                 MENU_ACTION_ITEM, "Close", domenu,
  93.                 0);
  94.         text[i] = window_create(frame, TEXTSW,
  95.             WIN_ERROR_MSG,        "Couldn't create subwindow",
  96.             WIN_IGNORE_PICK_EVENT,    WIN_RESIZE,
  97.             TEXTSW_DISABLE_CD,    TRUE,
  98.             TEXTSW_DISABLE_LOAD,    TRUE,
  99.             TEXTSW_INSERT_MAKES_VISIBLE, TEXTSW_ALWAYS,
  100.             TEXTSW_IGNORE_LIMIT,    TEXTSW_INFINITY,
  101.             TEXTSW_MENU,        menu[i],
  102.             0);
  103.     }
  104. }
  105.  
  106. /*
  107.  * Set all the window sizes.  This gets called whenever the base
  108.  * frame gets resized, and once at initialization.
  109.  *
  110.  * For now, all the subwindows are assumed to be of equal size.
  111.  */
  112. set_window_sizes()
  113. {
  114.     int i, fr_height, fr_width, ts_height, ts_width;
  115.  
  116.     fr_height = (int)window_get(frame, WIN_HEIGHT) -
  117.         (int)window_get(frame, WIN_TOP_MARGIN);
  118.     fr_width = (int)window_get(frame, WIN_WIDTH) -
  119.         LMARGIN - RMARGIN;
  120.     ts_height = fr_height/files - SMARGIN;
  121.     ts_width = fr_width;
  122.  
  123.     for (i=0; i<files; i++)
  124.     {
  125.         window_set(text[i],
  126.             WIN_HEIGHT, ts_height,
  127.             WIN_WIDTH, ts_width,
  128.             0);
  129.         if (i)
  130.             window_set(text[i], WIN_BELOW, text[i-1], 0);
  131.     }
  132. }
  133.  
  134. /*
  135.  * Parse command line arguments.
  136.  * For now, this is just a list of filenames.
  137.  */
  138. parse_args(c, v)
  139. char **v;
  140. {
  141.     int i, nflag = 0;
  142.  
  143.     files = 0;
  144.     for (i=1; i<c; i++)
  145.     {
  146.         if (! strcmp(v[i], "-n"))
  147.             nflag = 1;
  148.         else if (access(v[i], R_OK) == 0)
  149.         {
  150.             file[files] = v[i];
  151.             length[files] = MAXINT;
  152.             alert[files] = !nflag;
  153.             nflag = 0;
  154.             if (++files == 16)
  155.                 break;
  156.         }
  157.         else
  158.             perror(v[i]);
  159.     }
  160.     if (! files)
  161.         exit(1);
  162. }
  163.  
  164. /*
  165.  * Load all the files into their windows, and place the cursors at the
  166.  * infinity position.  This gets called once every second.
  167.  */
  168. load_files()
  169. {
  170.     int i;
  171.     struct stat st;
  172.  
  173.     for (i=0; i<files; i++)
  174.     {
  175.         if (stat(file[i], &st) < 0 || access(file[i], R_OK))
  176.         {
  177.             kill_file(i);
  178.             continue;
  179.         }
  180.         if (st.st_size == length[i])
  181.             continue;
  182.         if (st.st_size < length[i])    /* file has gotten smaller */
  183.             window_set(text[i], TEXTSW_FILE, file[i], 0);
  184.         else if (st.st_size > length[i])
  185.         {
  186.             char *buf;
  187.             int  fd, bsiz;
  188.  
  189.             buf = (char *)malloc(bsiz = (st.st_size - length[i]));
  190.             fd = open(file[i], O_RDONLY);
  191.             if (fd < 0)
  192.             {
  193. filerror:
  194.                 free(buf);
  195.                 kill_file(i);
  196.             }
  197.             if (lseek(fd, length[i], L_SET) < 0)
  198.                 goto filerror;
  199.             if (read(fd, buf, bsiz) < 0)
  200.                 goto filerror;
  201.  
  202.             window_set(text[i],
  203.                 TEXTSW_INSERTION_POINT, TEXTSW_INFINITY,
  204.                 0);
  205.             textsw_insert(text[i], buf, bsiz);
  206.             textsw_possibly_normalize(text[i], (Textsw_index)length[i]);
  207.             free(buf);
  208.         }
  209.         length[i] = st.st_size;
  210.         if (alert[i])
  211.             newstuff++;
  212.     }
  213.     if (newstuff)
  214.         if ((int)window_get(frame, FRAME_CLOSED))
  215.         {
  216.             inum ^= 3;
  217.             window_set(frame, FRAME_ICON, ikes[inum], 0);
  218.         }
  219.         else
  220.         {
  221.             newstuff = 0;
  222.             window_set(frame, FRAME_ICON, ikes[0], 0);
  223.         }
  224. }
  225.  
  226. /*
  227.  * Handle events.
  228.  */
  229. Notify_value
  230. event(window, event, arg, type)
  231. Window window;
  232. Event *event;
  233. Notify_arg arg;
  234. Notify_event_type type;
  235. {
  236.     Notify_value value;
  237.  
  238.     value = notify_next_event_func(window, event, arg, type);
  239.     if (event_id(event) == WIN_RESIZE)
  240.         set_window_sizes();
  241.     return(value);
  242. }
  243.  
  244. /*
  245.  * Handle a menu selection.
  246.  */
  247. domenu(m, mi)
  248. Menu m;
  249. Menu_item mi;
  250. {
  251.     int win;
  252.  
  253.     for (win = 0; win < files; win++)
  254.         if (menu[win] == m)
  255.             break;
  256.     if (win == files)
  257.         return;
  258.     if ((int)menu_get(m, MENU_SELECTED) == 2)
  259.         kill_file(win);
  260. }
  261.  
  262. /*
  263.  * Kill a file, either because we got an error reading it or because
  264.  * the user said so.
  265.  */
  266. kill_file(num)
  267. int num;
  268. {
  269.     int i;
  270.  
  271.     menu_destroy(menu[num]);
  272.     window_destroy(text[num]);
  273.     if (num != files-1)
  274.     {
  275.         for (i = num+1; i < files; i++)
  276.         {
  277.             menu[i-1] = menu[i];
  278.             text[i-1] = text[i];
  279.             file[i-1] = file[i];
  280.             length[i-1] = length[i];
  281.             alert[i-1] = alert[i];
  282.         }
  283.     }
  284.     if (num == 0)
  285.         window_set(text[0], WIN_Y, 0, 0);
  286.     if (--files == 0)
  287.         exit(0);
  288.     set_window_sizes();
  289. }
  290.  
  291. /*
  292.  * Set up a timer.  It checks all the files once a second.
  293.  * Also, tell the notifier what to do about resizes and so forth.
  294.  */
  295. set_notifier()
  296. {
  297.     static struct itimerval timer; /* this is our handle */
  298.  
  299.     bzero(&timer, sizeof(timer));
  300.     timer.it_interval.tv_sec = 1;
  301.     timer.it_value.tv_sec = 1;
  302.     notify_set_itimer_func(&timer, load_files, ITIMER_REAL, &timer, NULL);
  303.     notify_interpose_event_func(frame, event, NOTIFY_SAFE);
  304. }
  305.