home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / xv / xvhelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  14.3 KB  |  603 lines

  1. /* XView help viewer routines.
  2.    Copyright (C) 1995 Jakub Jelinek.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <config.h>
  19.  
  20. #include <X11/Xlib.h>
  21. #include <X11/cursorfont.h>
  22. #include <xview/xview.h>
  23. #include <xview/frame.h>
  24. #include <xview/panel.h>
  25. #include <xview/svrimage.h>
  26. #include <xview/canvas.h>
  27. #include <xview/scrollbar.h>
  28. #include <xview/cms.h>
  29. #include <xview/xv_xrect.h>
  30. #include "help.h"
  31. #include "../src/mad.h"
  32. #include "../src/util.h"
  33. #include "xvmain.h"
  34.  
  35. #include "help.icons"
  36.  
  37. #define TOPMARGIN 10
  38. #define LEFTMARGIN 10
  39. #define RIGHTMARGIN 10
  40. #define BOTTOMMARGIN 10
  41.  
  42. extern Frame mcframe;
  43. extern Server_image mcimage; /* xvinfo.c */
  44. Frame helpframe = XV_NULL;
  45. Panel helppanel;
  46. Canvas helpcanvas;
  47. Cms helpcms;
  48. extern Display *dpy;
  49. typedef struct {
  50.     Xv_Font font;
  51.     GC gc;
  52.     int height;
  53. } fontstruct;
  54.  
  55. extern char *currentpoint, *startpoint;
  56. static void repaint (void);
  57. static void clear_link_areas (void);
  58.  
  59. static void x_index_cmd (void)
  60. {
  61.     help_index_cmd ();
  62.     repaint ();
  63. }
  64.  
  65. static void x_back_cmd (void)
  66. {
  67. }
  68.  
  69. static void x_previous_cmd (void)
  70. {
  71. }
  72.  
  73. static void x_next_cmd (void)
  74. {
  75. }
  76.  
  77. static void x_search_cmd (void)
  78. {
  79. }
  80.  
  81. static void x_help_on_help (void)
  82. {
  83.     help_help_cmd ();
  84.     repaint ();
  85. }
  86.  
  87. static void x_quit_cmd (void)
  88. {
  89.     xv_destroy_safe (helpframe);
  90.     clear_link_areas ();
  91.     helpframe = XV_NULL;
  92.     interactive_display_finish ();
  93.     xv_dispatch_a_bit ();
  94. }
  95.  
  96. fontstruct getfont (char *name, int fg)
  97. {
  98.     fontstruct f;
  99.     XGCValues gcvalues;
  100.     
  101.     f.font = (Xv_Font) xv_find (helpcanvas, FONT, FONT_NAME, name, NULL);
  102.     if (f.font == XV_NULL)
  103.         f.font = (Xv_Font) xv_get (helpframe, XV_FONT);
  104.     gcvalues.font = (Font) xv_get (f.font, XV_XID);
  105.     gcvalues.foreground = (unsigned long) xv_get (helpcms, CMS_PIXEL, fg);
  106.     gcvalues.background = (unsigned long) xv_get (helpcms, CMS_BACKGROUND_PIXEL);    
  107.     gcvalues.graphics_exposures = FALSE;
  108.     f.gc = XCreateGC (dpy, RootWindow (dpy, DefaultScreen (dpy)), 
  109.         GCForeground|GCBackground|GCFont|GCGraphicsExposures, &gcvalues);
  110.     f.height = xv_get (f.font, FONT_DEFAULT_CHAR_HEIGHT);
  111.     return f;
  112. }
  113.  
  114. static char buffer [200];
  115. int x, h, y;
  116. int bufferindex;
  117. fontstruct fonormal, fobold, folink, fotitle;
  118. #define NORMAL &fonormal
  119. #define BOLD &fobold
  120. #define LINK &folink
  121. #define TITLE &fotitle
  122. fontstruct *curfont, *linefont, *wordfont;
  123. int startup;
  124. int paintwidth;
  125. Window xId;
  126. char *linebegin, *wordbegin;
  127. int tabsize = 30;
  128. struct area;
  129. typedef struct area *AREA;
  130. struct area {
  131.     int wx;  /* West x, Northwest y, Southwest y etc. */
  132.     int nwy;
  133.     int swy;
  134.     int ex;
  135.     int ney;
  136.     int sey;
  137.     char *jump;
  138.     AREA next;
  139. };
  140. AREA firstarea = NULL, lastarea = NULL;
  141. int do_link_areas = 1;
  142. static int painting = 1, linepainting = 1;
  143.  
  144. static void clear_link_areas (void)
  145. {
  146.     AREA p;
  147.     
  148.     while (firstarea != NULL) {
  149.         p = firstarea;
  150.         firstarea = firstarea->next;
  151.         free (p);
  152.     }
  153.     lastarea = NULL;
  154. }
  155.  
  156. static void start_link_area (char *link, int test)
  157. {
  158.     AREA p;
  159.     
  160.     if (test || !do_link_areas)
  161.         return;
  162.     
  163.     p = (AREA) xmalloc (sizeof (struct area), "Help link area");
  164.     if (firstarea != NULL)
  165.         lastarea->next = p;
  166.     else
  167.         firstarea = p;
  168.     lastarea = p;
  169.     p->wx = x;
  170.     p->nwy = y - h;
  171.     p->swy = y;
  172.     p->ex = x;
  173.     p->ney = y - h;
  174.     p->sey = y;
  175.     p->jump = link;
  176.     p->next = NULL;
  177. }
  178.  
  179. static void end_link_area (int test)
  180. {
  181.     if (test || !do_link_areas || !lastarea)
  182.         return;
  183.     
  184.     lastarea->ex = x;
  185.     lastarea->ney = y - h;
  186.     lastarea->sey = y;
  187. }
  188.  
  189. static AREA is_in_area (int x, int y)
  190. {
  191.     AREA p;
  192.     
  193.     for (p = firstarea; p != (AREA) NULL; p = p->next) {
  194.         if (y < p->nwy || y >= p->sey)
  195.             continue;
  196.         if (y < p->swy) {
  197.             if (x < p->wx)
  198.                 continue;
  199.             if (p->nwy == p->ney && x >= p->ex)
  200.                 continue;
  201.         } else if (y >= p->ney) {
  202.             if (x >= p->ex)
  203.                 continue;
  204.         }
  205.         return p;
  206.     }
  207.     return NULL;
  208. }
  209.  
  210. static void hparse (char *paint_start, int test);
  211.  
  212. static void setfont (fontstruct *f)
  213. {
  214.     curfont = f;
  215. }
  216.  
  217. static void newline (void)
  218. {
  219.     x = LEFTMARGIN;
  220.     y += h;
  221.     curfont = linefont;
  222.     hparse (linebegin, 0);
  223.     h = 0;
  224.     x = LEFTMARGIN;
  225.     linepainting = painting;
  226.     linebegin = wordbegin;
  227.     linefont = curfont;
  228. }
  229.  
  230. static int flush (char *p, int test)
  231. {
  232.     Font_string_dims dims;
  233.  
  234.     buffer [bufferindex] = 0;
  235.     xv_get (curfont->font, FONT_STRING_DIMS, buffer, &dims);
  236.     if (x + dims.width > paintwidth - RIGHTMARGIN && x) {
  237.         if (test)
  238.             newline ();
  239.         else
  240.             return 1;
  241.     }
  242.     if (!test) {
  243.         XDrawString (dpy, xId, curfont->gc, x, y, buffer, strlen (buffer));
  244.     }
  245.     x += dims.width;
  246.     if (dims.height > h)
  247.         h = dims.height;
  248.     wordbegin = p + 1;
  249.     bufferindex = 0;
  250.     return 0;
  251.  
  252. static void hparse (char *paint_start, int test)
  253. {
  254.     char *p;
  255.     int  c;
  256.  
  257.     if (test) {
  258.         painting = 1;
  259.         linepainting = 1;
  260.     } else
  261.         painting = linepainting;
  262.         
  263.     if (test)
  264.         setfont (NORMAL);
  265.     h = 0;
  266.     x = LEFTMARGIN;
  267.     bufferindex = 0;
  268.     if (test) {
  269.         wordbegin = paint_start;
  270.         linebegin = paint_start;
  271.         linefont = curfont;
  272.     }
  273.     
  274.     for (p = paint_start; *p != CHAR_NODE_END; p++){
  275.     c = *p;
  276.     switch (c){
  277.     case CHAR_LINK_START:
  278.         if (flush (p, test))
  279.             return;
  280.         setfont (LINK);
  281.         start_link_area (p, test);
  282.         break;
  283.     case CHAR_LINK_POINTER:
  284.         if (flush (p, test))
  285.             return;
  286.         setfont (NORMAL);
  287.         painting = 0;
  288.         end_link_area (test);
  289.         break;
  290.     case CHAR_LINK_END:
  291.         painting = 1;
  292.         break;
  293.     case CHAR_ALTERNATE:
  294.         break;
  295.     case CHAR_NORMAL:
  296.         break;
  297.     case CHAR_VERSION:
  298.         strcpy (buffer + bufferindex, VERSION);
  299.         bufferindex += strlen (VERSION);
  300.         break;
  301.     case CHAR_BOLD_ON:
  302.         if (flush (p, test))
  303.             return;
  304.         setfont (BOLD);
  305.         break;
  306.     case CHAR_BOLD_OFF:
  307.         if (flush (p, test))
  308.             return;
  309.         setfont (NORMAL);
  310.         break;
  311.     case CHAR_MCLOGO:
  312.         {
  313.             int mcimage_width = (int) xv_get (mcimage, XV_WIDTH);
  314.             int mcimage_height = (int) xv_get (mcimage, XV_HEIGHT);
  315.         
  316.             if (flush (p, test))
  317.                 return;
  318.             if (!test) {
  319.                 XCopyArea (dpy, 
  320.                     (Drawable) xv_get (mcimage, SERVER_IMAGE_PIXMAP),
  321.                     xId, curfont->gc, 0,0, mcimage_width, mcimage_height,
  322.                     x, y - mcimage_height);
  323.             }
  324.             x += mcimage_width;
  325.             if (h < mcimage_height)
  326.                 h = mcimage_height;
  327.             break;
  328.         }
  329.     case CHAR_TEXTONLY_START:
  330.         while (*p && *p != CHAR_NODE_END && *p != CHAR_TEXTONLY_END)
  331.             p++;
  332.         if (*p != CHAR_TEXTONLY_END)
  333.             p--;
  334.         break;
  335.     case CHAR_XONLY_START:
  336.     case CHAR_XONLY_END:
  337.         break;
  338.     case '\n':
  339.         if (p [1] == '\n') {
  340.             if (flush (p, test))
  341.                 return;
  342.             if (x > LEFTMARGIN) {
  343.                 if (!test)
  344.                     return;
  345.                 else
  346.                     newline ();
  347.             }
  348.             break;
  349.         }
  350.     case ' ':
  351.         buffer [bufferindex++] = ' ';
  352.         if (flush (p, test))
  353.             return;
  354.         break;
  355.     case '\t':
  356.         if (flush (p, test))
  357.             return;
  358.         x = (x + tabsize - LEFTMARGIN) / tabsize * tabsize + LEFTMARGIN;
  359.         if (x > paintwidth - RIGHTMARGIN) {
  360.             if (!test)
  361.                 return;
  362.             else
  363.                 newline ();
  364.             x = tabsize + LEFTMARGIN;
  365.         }
  366.         break;
  367.     default:
  368.         if (!painting)
  369.         continue;
  370.         buffer [bufferindex++] = c;
  371.         break;
  372.     }
  373.     }
  374.     if (flush (p, test))
  375.        return;
  376.     if (x > LEFTMARGIN) {
  377.         if (!test)
  378.             return;
  379.         else
  380.             newline ();
  381.     }
  382. }
  383.  
  384. static void canvas_repaint (Canvas canvas, Xv_Window paint)
  385. {
  386.     if (startup)
  387.         return;
  388.     xId = (Window) xv_get (paint, XV_XID);
  389.     y = TOPMARGIN;
  390.     paintwidth = (int) xv_get (xv_get (paint, CANVAS_PAINT_VIEW_WINDOW), XV_WIDTH);
  391.     XClearWindow (dpy, xId);
  392.     hparse (startpoint, 1);
  393.     XFlush (dpy);
  394. }
  395.  
  396. static void canvas_resize (Canvas canvas, int width, int height)
  397. {
  398.     if (startup)
  399.         return;
  400.     if (width != paintwidth)
  401.         repaint ();
  402. }
  403.  
  404. static void repaint (void) 
  405. {
  406.     Xv_Window paint, view;
  407.     Scrollbar scroll;
  408.  
  409.     clear_link_areas ();
  410.     do_link_areas = 1;
  411.     OPENWIN_EACH_VIEW (helpcanvas, view)
  412.         paint = (Xv_Window) xv_get (view, CANVAS_VIEW_PAINT_WINDOW);
  413.         canvas_repaint (helpcanvas, paint);
  414.         if (do_link_areas) {
  415.             do_link_areas = 0;
  416.             xv_set (helpcanvas,
  417.                 CANVAS_MIN_PAINT_HEIGHT, y + BOTTOMMARGIN,
  418.                 NULL);
  419.         }
  420.         scroll = (Scrollbar) xv_get (helpcanvas, 
  421.             OPENWIN_VERTICAL_SCROLLBAR, view);
  422.             
  423.         if (scroll != XV_NULL) {
  424.             xv_set (scroll,
  425.                 SCROLLBAR_VIEW_START, 0,
  426.                 NULL);
  427.             xv_set (scroll,
  428.                 SCROLLBAR_OBJECT_LENGTH, y + BOTTOMMARGIN,
  429.                 NULL);
  430.         }
  431.     OPENWIN_END_EACH
  432. }
  433.  
  434. static struct {
  435.     unsigned short *bits;
  436.     void (*callback) (void);
  437. } buttons [] = { 
  438. index_bits, x_index_cmd,
  439. back_bits, x_back_cmd,
  440. previous_bits, x_previous_cmd,
  441. next_bits, x_next_cmd,
  442. search_bits, x_search_cmd };
  443. Cursor cursors [2];
  444.  
  445. static void event_handler (Xv_Window paint, Event *event)
  446. {
  447.     int x, y;
  448.     AREA p;
  449.     static int current_cursor = 0;
  450.  
  451.     switch (event_action (event)) {
  452.         case ACTION_SELECT:
  453.             x = event_x (event);
  454.             y = event_y (event);
  455.             p = is_in_area (x, y);
  456.             if (p != NULL && p->jump != NULL) {
  457.                 currentpoint = startpoint = help_follow_link (startpoint, p->jump);
  458.                 repaint ();
  459.             }
  460.             break;
  461.         case LOC_MOVE:
  462.             x = event_x (event);
  463.             y = event_y (event);
  464.             p = is_in_area (x, y);
  465.             if (p != NULL) {
  466.                 if (!current_cursor) {
  467.                     XDefineCursor (dpy, xv_get (paint, XV_XID), cursors [1]);
  468.                     current_cursor = 1;
  469.                 }
  470.             } else {
  471.                 if (current_cursor) {
  472.                     XDefineCursor (dpy, xv_get (paint, XV_XID), cursors [0]);
  473.                     current_cursor = 0;
  474.                 }
  475.             }
  476.             break;
  477.     }
  478. }
  479.  
  480. static void create_frame (void)
  481. {
  482.     Panel_button_item button;
  483.     int i;
  484.  
  485.     helpcms = (Cms) xv_create (XV_NULL, CMS,
  486.         CMS_CONTROL_CMS, TRUE,
  487.         CMS_SIZE, CMS_CONTROL_COLORS + 5,
  488.         CMS_NAMED_COLORS, "black", "black", "green4", "red4", "black", NULL,
  489.         NULL);
  490.         
  491.     helpframe = xv_create (mcframe, FRAME, 
  492.         FRAME_LABEL, "Midnight X Commander Help",
  493.         WIN_CMS, helpcms,
  494.         FRAME_INHERIT_COLORS, TRUE,
  495.         NULL);
  496.     
  497.     helppanel = xv_create (helpframe, PANEL,
  498.         NULL);
  499.         
  500.     xv_create (helppanel, PANEL_BUTTON,
  501.         PANEL_LABEL_STRING, "Help",
  502.         PANEL_ITEM_MENU, xv_create (XV_NULL, MENU,
  503.             MENU_ITEM,
  504.                 MENU_STRING, "Help on Help",
  505.                 MENU_NOTIFY_PROC, x_help_on_help,
  506.                 NULL,
  507.             MENU_ITEM,
  508.                 MENU_STRING, "Index",
  509.                 MENU_NOTIFY_PROC, x_index_cmd,
  510.                 NULL,
  511.             MENU_ITEM,
  512.                 MENU_STRING, "Back",
  513.                 MENU_NOTIFY_PROC, x_back_cmd,
  514.                 NULL,
  515.             MENU_ITEM,
  516.                 MENU_STRING, "Previous",
  517.                 MENU_NOTIFY_PROC, x_previous_cmd,
  518.                 NULL,
  519.             MENU_ITEM,
  520.                 MENU_STRING, "Next",
  521.                 MENU_NOTIFY_PROC, x_next_cmd,
  522.                 NULL,
  523.             MENU_ITEM,
  524.                 MENU_STRING, "Search",
  525.                 MENU_NOTIFY_PROC, x_search_cmd,
  526.                 NULL,
  527.             NULL),
  528.         NULL);
  529.     button = (Panel_button_item) xv_create (helppanel, PANEL_BUTTON,
  530.         PANEL_LABEL_STRING, "Quit",
  531.         PANEL_NOTIFY_PROC, x_quit_cmd,
  532.         NULL);
  533.     for (i = 0; i < sizeof (buttons) / sizeof (buttons [0]); i++) {
  534.         button = (Panel_button_item) xv_create (helppanel, PANEL_BUTTON,
  535.             PANEL_LABEL_IMAGE, xv_create (XV_NULL, SERVER_IMAGE,
  536.                 SERVER_IMAGE_DEPTH, 1,
  537.                 XV_WIDTH, 48,
  538.                 XV_HEIGHT, 48,
  539.                 SERVER_IMAGE_BITS, buttons [i].bits,
  540.                 NULL),
  541.             PANEL_NOTIFY_PROC, buttons [i].callback,
  542.             NULL);
  543.         if (!i)
  544.             xv_set (button,
  545.             PANEL_NEXT_ROW, -1,
  546.         NULL);
  547.     }
  548.  
  549.     window_fit (helppanel);
  550.     
  551.     xv_set (helpframe,
  552.         XV_WIDTH, xv_get (helppanel, XV_WIDTH),
  553.         NULL);
  554.         
  555.     xv_set (helppanel,
  556.         XV_WIDTH, WIN_EXTEND_TO_EDGE,
  557.         NULL);
  558.         
  559.     startup = 1;
  560.         
  561.     helpcanvas = xv_create (helpframe, CANVAS,
  562.         WIN_BELOW, helppanel,
  563.         CANVAS_REPAINT_PROC, canvas_repaint,
  564.         CANVAS_RESIZE_PROC, canvas_resize,
  565.         CANVAS_X_PAINT_WINDOW, FALSE,
  566.         CANVAS_PAINTWINDOW_ATTRS,
  567.             WIN_CONSUME_EVENTS,
  568.             WIN_MOUSE_BUTTONS, LOC_MOVE, NULL,
  569.             WIN_EVENT_PROC, event_handler,
  570.             NULL,
  571.         NULL);
  572.         
  573.     cursors [0] = (Cursor) xv_get (xv_get (helpcanvas, WIN_CURSOR), XV_XID);
  574.     cursors [1] = XCreateFontCursor (dpy, XC_hand2);
  575.         
  576.     xv_create (helpcanvas, SCROLLBAR,
  577.         SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL,
  578.         SCROLLBAR_SPLITTABLE, TRUE,
  579.         NULL);
  580.         
  581.     fonormal = getfont ("lucidasans-12", CMS_CONTROL_COLORS);
  582.     fobold = getfont ("lucidasans-bold-12", CMS_CONTROL_COLORS + 1);
  583.     folink = getfont ("lucidasans-12", CMS_CONTROL_COLORS + 2);
  584.     fotitle = getfont ("lucidasans-bold-18", CMS_CONTROL_COLORS + 3);
  585.     
  586.     window_fit (helpframe);
  587.     
  588.     xv_set (helpframe,
  589.         XV_SHOW, TRUE,
  590.         NULL);
  591.         
  592.     startup = 0;
  593.         
  594.     repaint ();
  595. }
  596.  
  597. void x_interactive_display (void)
  598. {
  599.     if (helpframe == XV_NULL)
  600.         create_frame ();
  601. }
  602.