status.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:28k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* a status bar at bottom on window */
  2. #include <stdarg.h>
  3. #include <stdio.h>  /* STUPID ALPHA/OSF - GCC !!!!! */
  4. #include <X11/Xlib.h>
  5. #include <X11/Xutil.h>
  6. #include <X11/Xos.h>
  7. #include <X11/keysym.h>
  8. #include "HTUtils.h" /* WWW general purpose macros */
  9. #include "tcp.h"
  10. #include "HTList.h"
  11. #include "HTAccess.h"
  12. #include "www.h"
  13. #define LEFTMARGIN    50
  14. #define RIGHTMARGIN   7
  15. #define status_width    (win_width - ICON_WIDTH)
  16. extern int debug;
  17. extern int initialised;   /* if false it is unsafe to do X output */
  18. extern int busy;
  19. extern Display *display;
  20. extern int screen;
  21. extern int sbar_width;
  22. extern XFontStruct *pFontInfo;
  23. extern unsigned long textColor, labelColor, windowColor, strikeColor,
  24.                      windowTopShadow, windowBottomShadow, statusColor;
  25. #ifdef SELECTION
  26. #include <X11/Xatom.h>
  27. extern unsigned long statusSelectColor; /* howcome 1/9/94 */
  28. #endif
  29. extern unsigned int win_width, win_height;
  30. extern char *user;
  31. char *gatewayUser; /* howcome 20/9/94: removed extern since tcp.c no longer is loaded */
  32. extern int ToolBarHeight;
  33. extern Doc *CurrentDoc; /*, NewDoc; */
  34. #define STATSIZ 256
  35. #define ActiveTextColor labelColor
  36. extern Window win;
  37. GC status_gc;
  38. int statusHeight;
  39. char status[STATSIZ];
  40. char authreq[STATSIZ];
  41. int AbortFlag;
  42. int AbortButton = 1;
  43. int AbortButtonChanged = 0;
  44. int ABup = 1;
  45. int OpenURL;
  46. int FindStr;
  47. int IsIndex;
  48. int SaveFile;
  49. int Authorize;
  50. int statusOffset;
  51. int cursor; /* position of cursor */
  52. #ifdef SELECTION
  53. int startSelect, stopSelect, beginChr, endChr, textWidth=1;
  54. Bool selecting = False;
  55. #endif
  56. /* save strings for specific funcions */
  57. char *OpenString;
  58. char *SaveAsString;
  59. char *FindStrVal;
  60. char *SearchStrVal;
  61. char *FindNextStr;
  62. static int charheight;
  63. static XFontStruct *pStatusFontInfo;
  64. static Button abButton;
  65. void SetStatusWin(Window aWin)
  66. {
  67.     win = aWin;
  68. }
  69. void SetStatusGC(GC aGC)
  70. {
  71.     status_gc = aGC;
  72. }
  73. void SetStatusFont(XFontStruct *pf)
  74. {
  75.     pStatusFontInfo = pf;
  76.     charheight = pf->max_bounds.ascent + pf->max_bounds.descent;
  77.     statusHeight = (Authorize ? 16 + (charheight<<1) : 14 + charheight);
  78.     abButton.label = "Abort";
  79. }
  80. char *LabelString(int *len)
  81. {
  82.     if (OpenURL)
  83.     {
  84.         *len = 5;
  85.         return "Open:";
  86.     }
  87.     if (SaveFile)
  88.     {
  89.         *len = 7;
  90.         return "SaveAs:";
  91.     }
  92.     if (FindStr)
  93.     {
  94.         *len = 5;
  95.         return "Find:";
  96.     }
  97.     if (IsIndex)
  98.     {
  99.         *len = 6;
  100.         return "Match:";
  101.     }
  102.     return NULL;
  103. }
  104. int StatusActive(void)
  105. {
  106.     int c;
  107.     return (Authorize || LabelString(&c));
  108. }
  109. void RestoreStatusString(void)
  110. {
  111.     if (OpenURL)
  112.     {
  113.         if (OpenString)
  114.             strcpy(status, OpenString);
  115.         else
  116.             *status = '';
  117.     }
  118.     else if (SaveFile)
  119.     {
  120.         if (SaveAsString)
  121.             strcpy(status, SaveAsString);
  122.         else
  123.             *status = '';
  124.     }
  125.     else if (FindStr)
  126.     {
  127.         if (FindStrVal)
  128.             strcpy(status, FindStrVal);
  129.         else
  130.             *status = '';
  131.     }
  132.     else if (IsIndex)
  133.     {
  134.         if (SearchStrVal)
  135.             strcpy(status, SearchStrVal);
  136.         else
  137.             *status = '';
  138.     }
  139. #ifdef SELCTION
  140.     beginChr = 0;
  141.     endChr = 0;
  142. #endif
  143.     cursor = strlen(status);
  144. }
  145. void SaveStatusString(void)
  146. {
  147.     if (OpenURL)
  148.     {
  149.         if (OpenString)
  150.             Free(OpenString);
  151.         OpenString = strdup(status);
  152.     }
  153.     else if (SaveFile)
  154.     {
  155.         if (SaveAsString)
  156.             Free(SaveAsString);
  157.         SaveAsString = strdup(status);
  158.     }
  159.     else if (FindStr)
  160.     {
  161.         if (FindStrVal)
  162.             Free(FindStrVal);
  163.         FindStrVal = strdup(status);
  164.     }
  165.     else if (IsIndex)
  166.     {
  167.         if (SearchStrVal)
  168.             Free(SearchStrVal);
  169.         SearchStrVal = strdup(status);
  170.     }
  171. }
  172. /* functions DrawOutSet amd DrawInSet changed by Janet for more general use (added Window argument)*/
  173. void DrawOutSet(Window aWin,GC gc, int x, int y, unsigned int w, unsigned int h)
  174. {
  175.     XSetForeground(display, gc, windowTopShadow);
  176.     XFillRectangle(display, aWin, gc, x, y, w, 1);
  177.     XFillRectangle(display, aWin, gc, x, y+1, w-1, 1);
  178.     XFillRectangle(display, aWin, gc, x, y, 1, h);
  179.     XFillRectangle(display, aWin, gc, x+1, y+1, 1, h-1);
  180.     XSetForeground(display, gc, windowBottomShadow);
  181.     XFillRectangle(display, aWin, gc, x, y+h-1, w, 1);
  182.     XFillRectangle(display, aWin, gc, x+1, y+h-2, w-1, 1);
  183.     XFillRectangle(display, aWin, gc, x+w-1, y, 1, h);
  184.     XFillRectangle(display, aWin, gc, x+w-2, y+1, 1, h-1);
  185. }
  186. void DrawInSet(Window aWin, GC gc, int x, int y, unsigned int w, unsigned int h)
  187. {
  188.     XSetForeground(display, gc, windowBottomShadow);
  189.     XFillRectangle(display, aWin, gc, x, y, w, 1);
  190.     XFillRectangle(display, aWin, gc, x, y+1, w-1, 1);
  191.     XFillRectangle(display, aWin, gc, x, y, 1, h);
  192.     XFillRectangle(display, aWin, gc, x+1, y+1, 1, h-1);
  193.     XSetForeground(display, gc, windowTopShadow);
  194.     XFillRectangle(display, aWin, gc, x, y+h-1, w, 1);
  195.     XFillRectangle(display, aWin, gc, x+1, y+h-2, w-1, 1);
  196.     XFillRectangle(display, aWin, gc, x+w-1, y, 1, h);
  197.     XFillRectangle(display, aWin, gc, x+w-2, y+1, 1, h-1);
  198. }
  199. void DrawOutSetCircle(GC gc, int x, int y, unsigned int w, unsigned int h)
  200. {
  201.     XSetForeground(display, gc, windowTopShadow);
  202.     XDrawArc(display, win, gc, x, y, w, h, 45<<6, 180<<6);
  203.     XDrawArc(display, win, gc, x+1, y+1, w-2, h-2, 45<<6, 180<<6);
  204.     XSetForeground(display, gc, windowBottomShadow);
  205.     XDrawArc(display, win, gc, x, y, w, h, 225<<6, 180<<6);
  206.     XDrawArc(display, win, gc, x+1, y+1, w-2, h-2, 225<<6, 180<<6);
  207. }
  208. void DrawInSetCircle(GC gc, int x, int y, unsigned int w, unsigned int h)
  209. {
  210.     XSetForeground(display, gc, windowBottomShadow);
  211.     XDrawArc(display, win, gc, x, y, w, h, 45<<6, 180<<6);
  212.     XDrawArc(display, win, gc, x+1, y+1, w-2, h-2, 45<<6, 180<<6);
  213.     XSetForeground(display, gc, windowTopShadow);
  214.     XDrawArc(display, win, gc, x, y, w, h, 225<<6, 180<<6);
  215.     XDrawArc(display, win, gc, x+1, y+1, w-2, h-2, 225<<6, 180<<6);
  216. }
  217. void DisplayStatusBar()
  218. {
  219.     int x, y, r, n, active;
  220.     unsigned int w, h;
  221.     char *p, *s=NULL;
  222.     XRectangle rect;
  223.     active = ((Authorize || (s = LabelString(&n))) ? 1 : 0);
  224.     statusHeight = (Authorize ? 16 + (charheight<<1) : 14 + charheight);
  225.     rect.x = x = 0;
  226.     rect.y = y = StatusTop; 
  227.     rect.width = w = status_width;
  228.     rect.height = h = statusHeight;
  229.     XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  230.     XSetForeground(display, status_gc, windowColor);
  231.     XFillRectangle(display, win, status_gc, x, y, w, h);
  232.     DrawOutSet(win, status_gc, x, y, w, h);
  233.     if (Authorize)
  234.     {
  235.         XSetForeground(display, status_gc, labelColor);
  236.         rect.width -= 2;
  237.         XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  238.         XDrawString(display, win, status_gc,
  239.                 18, y + 3 + pStatusFontInfo->max_bounds.ascent,
  240.                 authreq, strlen(authreq));
  241.     }
  242.     /* howcome 24/2/95: by using a fixed LEFTMARGIN, we're unable to
  243.        scale the abort button horisontally */
  244.     x += LEFTMARGIN;
  245.     y = StatusTop + StatusFontOffset - 2;
  246.     h = 6 + charheight;
  247.     w -= LEFTMARGIN + RIGHTMARGIN;
  248.     XSetForeground(display, status_gc, (active ? statusColor : windowColor));
  249.     XFillRectangle(display, win, status_gc, x, y, w, h);
  250.     DrawInSet(win, status_gc, x, y, w, h);
  251.     /* needs a call to set clipping rectangle */
  252.     /* would currently interact with scrollbar gc */
  253.     rect.x = x + 2;
  254.     rect.y = y;
  255.     rect.width = w - 4;
  256.     rect.height = h;
  257.     r = XTextWidth(pStatusFontInfo, "Abort", 5) + 8;
  258.     abButton.x = 6;
  259.     abButton.y = y + 2;
  260.     abButton.w = r;
  261.     abButton.h = h-3;
  262.     if (AbortButton)
  263.     {
  264.         if (ABup)
  265.             DrawOutSet(win, status_gc, 6, y+2, r, h-3);
  266.         else
  267.             DrawInSet(win, status_gc, 6, y+2, r, h-3);
  268.         XSetForeground(display, status_gc, labelColor);
  269.         XDrawString(display, win, status_gc,
  270.                 10, y + 3 + pStatusFontInfo->max_bounds.ascent,
  271.                 "Abort", 5);
  272.     }
  273.     else if (s)
  274.     {
  275.         XSetForeground(display, status_gc, labelColor);
  276.         XDrawString(display, win, status_gc,
  277.             8, y + 2 + pStatusFontInfo->max_bounds.ascent, s, n);
  278.     }
  279.     else
  280.         XSetForeground(display, status_gc, labelColor);
  281.     if (Authorize && (p = strchr(status, ':')))
  282.         n = p - status + 1;
  283.     else
  284.         n = strlen(status);
  285.     XSetForeground(display, status_gc, (active ? ActiveTextColor : labelColor));
  286.     XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  287.     XDrawString(display, win, status_gc,
  288.         x + 4 - statusOffset, y + 2 + pStatusFontInfo->max_bounds.ascent,
  289.         status, n);
  290.     r = XTextWidth(pStatusFontInfo, status, cursor);
  291.     if (s || Authorize)   /* draw cursor */
  292.     {
  293.         XSetForeground(display, status_gc, strikeColor);
  294.         XFillRectangle(display, win, status_gc, x+3+r - statusOffset, y+2, 1, h-4);
  295.     }
  296. #ifdef SELECTION
  297.     /* howcome 2/8/94: added code to draw highlighted strings. 
  298.        b (=beginChr) and e (=endChr) contains the indexes to start 
  299.        and stop of highlighted chars in status string 
  300.        */
  301.     if (beginChr > 0) {
  302.       XSetForeground(display, status_gc, labelColor);
  303.       XDrawString(display, win, status_gc,
  304.   (x + 4 - statusOffset), y + 2 + pStatusFontInfo->max_bounds.ascent,
  305.   status,
  306.   min(n,beginChr));
  307.     }
  308.     if (beginChr < n) {
  309.       XSetForeground(display, status_gc, strikeColor);
  310.       XDrawString(display, win, status_gc,
  311.   (x + 4 - statusOffset) + (beginChr * textWidth), y + 2 + pStatusFontInfo->max_bounds.ascent,
  312.   (status + min(n,beginChr)),
  313.   (min(n,endChr) - min(n,beginChr)));
  314.     }
  315.     if (endChr < n) {
  316.       XSetForeground(display, status_gc, labelColor);
  317.       XDrawString(display, win, status_gc,
  318.   (x + 4 - statusOffset) + (endChr * textWidth), y + 2 + pStatusFontInfo->max_bounds.ascent,
  319.   (status + min(n,endChr)),
  320.   (n - min(n,endChr)));
  321.     }
  322.     r = XTextWidth(pStatusFontInfo, status, n);
  323.     if (s || Authorize)   /* draw cursor */
  324.     {
  325.         XSetForeground(display, status_gc, strikeColor);
  326.         XFillRectangle(display, win, status_gc, x+3+r - statusOffset, y+2, 1, h-4);
  327.     }
  328. #endif /* SELECTION */
  329. }
  330. #ifdef SELECTION
  331. /* howcome added SelectStatus 1/8/94 */
  332. void SelectStatus(int x_in, int y_in)
  333. {
  334.     int x, y; /* r, n, ch, active;*/ /* janet 21/07/95: not used */
  335.     /*    unsigned int w, h; */ /* janet 21/07/95: not used */
  336.     /*    char *p, *s; */ /* janet 21/07/95: not used */
  337.     /*    XRectangle rect; */  /* janet 21/07/95: not used */ 
  338.     if (selecting) {
  339.       x = 50;
  340.       y = win_height - 10 - charheight;
  341.       stopSelect = (x_in - x) / textWidth;
  342.       stopSelect = max(0,stopSelect);
  343.       
  344.       beginChr = min(startSelect,stopSelect);
  345.       endChr = max(startSelect,stopSelect);
  346.       
  347.       DisplayStatusBar();
  348.     }
  349. }
  350. #endif /* SELECTION */
  351. void SetStatusString(char *s)
  352. {
  353.     char *p;
  354.     int x, y, r, n, ch;
  355.     unsigned int w, h;
  356.     XRectangle rect;
  357.     if (initialised)
  358.     {
  359.         if (s)
  360.         {
  361.             strncpy(status, s, STATSIZ-1);
  362.             status[STATSIZ-1] = '';
  363.             /* trim trailing rn */
  364.             n = strlen(status) - 1;
  365.             if (n > 0 && status[n] == 'n')
  366.             {
  367.                 status[n--] = '';
  368.                 if (status[n] == 'r')
  369.                      status[n] = '';
  370.             }
  371.         }
  372.         ch = pStatusFontInfo->max_bounds.ascent + pStatusFontInfo->max_bounds.descent;
  373.         statusHeight = (Authorize ? 16 + (charheight<<1) : 14 + ch);
  374.         rect.x = x = 0;
  375.         rect.y = StatusTop; 
  376.         rect.width = w = status_width;
  377.         rect.height = statusHeight;
  378.         XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  379.         XSetForeground(display, status_gc, windowColor);
  380.         h = 14 + charheight;
  381.         y = rect.y + rect.height - h;
  382.         s = LabelString(&r);
  383.         if (AbortButton)
  384.         {
  385.             if (AbortButtonChanged)
  386.             {
  387.                 XFillRectangle(display, win, status_gc, 6, y+2, (LEFTMARGIN - 8), h-4);
  388.                 if (ABup)
  389.                     DrawOutSet(win, status_gc, abButton.x, abButton.y, abButton.w, abButton.h);
  390.                 else
  391.                     DrawInSet(win, status_gc, abButton.x, abButton.y, abButton.w, abButton.h);
  392.                 XSetForeground(display, status_gc, labelColor);
  393.                 XDrawString(display, win, status_gc,
  394.                         abButton.x + 4, abButton.y + 1 + pStatusFontInfo->max_bounds.ascent,
  395.                         "Abort", 5);
  396.                 AbortButtonChanged = 0;  /* avoid flickering buffer */
  397.             }
  398.         }
  399.         else if (s)
  400.         {
  401.             XFillRectangle(display, win, status_gc, 6, y+2, (LEFTMARGIN - 8), h-4);
  402.             XSetForeground(display, status_gc, labelColor);
  403.             XDrawString(display, win, status_gc,
  404.                 8, y + 6 + pStatusFontInfo->max_bounds.ascent, s, r);
  405.         }
  406.         else
  407.             XFillRectangle(display, win, status_gc, 6, y+2, (LEFTMARGIN - 8), h-4);
  408.         rect.x = x = LEFTMARGIN + 2;
  409.         rect.y = y = StatusTop + StatusFontOffset; 
  410.         rect.width = w = status_width - LEFTMARGIN - RIGHTMARGIN - 4;
  411.         rect.height = h = 2 + charheight;
  412.         XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  413.         XSetForeground(display, status_gc, ((s||Authorize) ? statusColor : windowColor) );
  414.         XFillRectangle(display, win, status_gc, x, y, w, h);
  415.         cursor = n = strlen(status);
  416.         if (Authorize && (p = strchr(status, ':')))
  417.             n = p - status + 1;
  418.         XSetForeground(display, status_gc, ((s || Authorize) ? ActiveTextColor : labelColor));
  419.         XDrawString(display, win, status_gc,
  420.             x + 2 - statusOffset, y + pStatusFontInfo->max_bounds.ascent,
  421.             status, n);
  422.         r = XTextWidth(pStatusFontInfo, status, cursor);
  423.         if (s||Authorize)   /* draw cursor */
  424.         {
  425.             XSetForeground(display, status_gc, strikeColor);
  426.             XFillRectangle(display, win, status_gc, x+1+r - statusOffset, y, 1, h);
  427.         }
  428.     }
  429.     else if (s)
  430.     {
  431.         strncpy(status, s, STATSIZ-1);
  432.         status[STATSIZ-1] = '';
  433.         /* trim trailing rn */
  434.         n = strlen(status) - 1;
  435.         if (n > 0 && status[n] == 'n')
  436.         {
  437.             status[n--] = '';
  438.             if (status[n] == 'r')
  439.                 status[n] = '';
  440.         }
  441.         cursor = strlen(status);
  442. #ifdef SELECTION
  443. ClearStatusSelection();
  444. #endif
  445.     }
  446.     XFlush(display); /* howcome 5/10/94: this seems to be required */
  447. }
  448. void RepairStatus(int x1, int moved)
  449. {
  450.     char *p;
  451.     int x, y, r, n, active;
  452.     unsigned int w, h;
  453.     XRectangle rect;
  454.     rect.x = x = LEFTMARGIN + 2;
  455.     rect.y = y = StatusTop + StatusFontOffset; 
  456.     rect.width = w = status_width - LEFTMARGIN - RIGHTMARGIN - 4;
  457.     rect.height = h = 2 + charheight;
  458.     if (!moved)
  459.     {
  460.         if (rect.x < x1)
  461.         {
  462.             rect.width -= x1 - x;
  463.             rect.x = x1;
  464.         }
  465. /*
  466.         r = statusHeight;
  467.         if (r < rect.width)
  468.             rect.width = r;
  469. */    }
  470.     active = ((Authorize || LabelString(&n)) ? 1 : 0);
  471.     XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  472.     XSetForeground(display, status_gc, (active ? statusColor : windowColor));
  473.     XFillRectangle(display, win, status_gc, x, y, w, h);
  474.     if (Authorize && (p = strchr(status, ':')))
  475.         n = p - status + 1;
  476.     else
  477.         n = strlen(status);
  478.     XSetForeground(display, status_gc, (active ? ActiveTextColor : labelColor));
  479.     XDrawString(display, win, status_gc,
  480.         x + 2 - statusOffset, y + pStatusFontInfo->max_bounds.ascent,
  481.         status, n);
  482.     r = XTextWidth(pStatusFontInfo, status, cursor);
  483.     if (Authorize || LabelString(&n))   /* draw cursor */
  484.     {
  485.         XSetForeground(display, status_gc, strikeColor);
  486.         XFillRectangle(display, win, status_gc, x+1+r - statusOffset, y, 1, h);
  487.     }
  488. }
  489. #ifdef SELECTION
  490. void ClearStatusSelection() /* howcome 2/8/94 */
  491. {
  492.     beginChr = 0;
  493.     endChr = 0;
  494. }
  495. #endif
  496. void ClearStatus()
  497. {
  498.     cursor = 0;
  499.     status[0] = '';
  500.     statusOffset = 0;
  501. #ifdef SELECTION
  502.     beginChr = 0;
  503.     endChr = 0;
  504. #endif
  505. }
  506. int IsEditChar(char c)
  507. {
  508.     if (c == 'b' || c == 'n' || c == 'r' || c == 21) /* 21 == ^U */
  509.         return 1;
  510.     if (c >= ' ')
  511.         return 1;
  512.     return 0;
  513. }
  514. void EditChar(char c)
  515. {
  516.     char *who;
  517.     int i, n, x1, x2, moved;
  518.     /* x1 is position of cursor, x2 is right edge of clipped text */
  519.     n = strlen(status);
  520.     if (busy && !Authorize)
  521.         Beep();
  522.     else if (c == 'b')
  523.     {
  524.         if (cursor > 0)
  525.         {
  526.             --cursor;
  527.             strcpy(status+cursor, status+cursor+1);
  528.             x1 = LEFTMARGIN + 4 + XTextWidth(pStatusFontInfo, status, cursor);
  529.             x2 = status_width - RIGHTMARGIN - 4;
  530.             n = (x1 > x2 ? x1 - x2 : 0);
  531.             moved = ( (n == statusOffset) ? 0 : 1);
  532.             statusOffset = n;
  533.             RepairStatus(x1 - statusOffset - 1, moved);
  534.         }
  535.         else
  536.             XBell(display, 0);
  537.     }
  538.     else if (c == 21) /* Ctrl-U */
  539.     {
  540. ClearStatus();
  541.         RepairStatus(statusOffset, 1);
  542.     }
  543.     else if (c == 127)  /* DEL */
  544.     {
  545.         if (cursor < strlen(status))
  546.         {
  547.             strcpy(status+cursor, status+cursor+1);
  548.             x1 = LEFTMARGIN + 4 + XTextWidth(pStatusFontInfo, status, cursor);
  549.             x2 = status_width - RIGHTMARGIN - 4;
  550.             n = (x1 > x2 ? x1 - x2 : 0);
  551.             moved = ( (n == statusOffset) ? 0 : 1);
  552.             statusOffset = n;
  553.             RepairStatus(x1 - statusOffset - 1, moved);
  554.         }
  555.         else
  556.             XBell(display, 0);
  557.     }
  558.     else if ((Authorize || LabelString(&i)) && (c == 'n' || c == 'r') )
  559.     {
  560.         SaveStatusString();
  561.         if (Authorize)
  562.         {
  563.             if (Authorize == GATEWAY)
  564.             {
  565.                 if (gatewayUser)
  566.                     Free(gatewayUser);
  567.                 gatewayUser = strdup(status);
  568.                 Authorize = 0;
  569.                 busy = 0;
  570.                 status[0] = '';
  571. #ifdef SELECTION
  572. beginChr = endChr = 0;
  573. #endif
  574.                 DisplayStatusBar();
  575.                 DisplaySizeChanged(0);
  576.                 DisplayScrollBar();
  577.                 i = 2 + charheight;
  578.                 DisplayDoc(WinLeft, WinBottom-i, WinWidth, i);
  579.                 XFlush(display);
  580. /*                OpenDoc(NewDoc.url, 0, (strchr(NewDoc.url, ':') ? REMOTE : LOCAL));*/
  581.             }
  582.             else
  583.             {
  584.                 who = strdup(status);
  585.                 Authorize = 0;
  586.                 busy = 0;
  587.                 status[0] = '';
  588. #ifdef SELECTION
  589. beginChr = endChr = 0; /* howcome */
  590. #endif
  591.                 DisplayStatusBar();
  592.                 DisplaySizeChanged(0);
  593.                 DisplayScrollBar();
  594.                 i = 2 + charheight;
  595.                 DisplayDoc(WinLeft, WinBottom-i, WinWidth, i);
  596.                 XFlush(display);
  597. /*                OpenDoc(NewDoc.url, who, (strchr(NewDoc.url, ':') ? REMOTE : LOCAL));*/
  598.                 Free(who);
  599.             }
  600.         }
  601.         else if (OpenURL) {
  602.     if (STATUS_TRACE)
  603. fprintf(stderr,"EditChar: calling OpenDoc(%s, NULL, %s)n",status, (strchr(status, ':') ? "REMOTE" : "LOCAL"));
  604. #ifdef __QNX__
  605.     /* assume http:// if no protocol specified */
  606.     if (strchr(status, ':') == 0) {
  607. memmove(status + sizeof "http://" - 1, status, strlen(status) + 1);
  608. memcpy(status, "http://", sizeof "http://" - 1);
  609.     }
  610. #endif
  611.             OpenDoc(status);
  612. }
  613.         else if (SaveFile)
  614.             SaveDoc(status);
  615.         else if (FindStr)
  616.         {
  617.             FindNextStr = 0;
  618.             FindString(status, &FindNextStr);
  619.         }
  620.         else if (IsIndex)
  621.             SearchIndex(status);
  622.     }
  623.     else if (c >= ' ')
  624.     {
  625.         if (n < STATSIZ-1)
  626.         {
  627.             for (i = n; i >= cursor; --i)
  628.                 status[i+1] = status[i];
  629.             status[cursor++] = c;
  630.             
  631.             x1 = LEFTMARGIN + 3 + XTextWidth(pStatusFontInfo, status, cursor);
  632.             x2 = status_width - RIGHTMARGIN - 4;
  633.             n = (x1 > x2 ? x1 - x2 : 0);
  634.             moved = ( (n == statusOffset) ? 0 : 1);
  635.             statusOffset = n;
  636.             RepairStatus(x1 - statusOffset - XTextWidth(pStatusFontInfo, &c, 1), moved);
  637.         }
  638.         else
  639.             XBell(display, 0);
  640.     }
  641. }
  642. void MoveStatusCursor(int key)
  643. {
  644.     int was, x, y, x1, x2, moved = 0, r, n;
  645.     unsigned int w, h;
  646.     XRectangle rect;
  647.     was = cursor;
  648.     if (key == XK_Left)
  649.     {
  650.         if (cursor > 0)
  651.         {
  652.             --cursor;
  653.             x1 = LEFTMARGIN + 4 + XTextWidth(pStatusFontInfo, status, cursor);
  654.             x2 = status_width - RIGHTMARGIN - 4;
  655.             n = (x1 > x2 ? x1 - x2 : 0);
  656.             moved = ( (n == statusOffset) ? 0 : 1);
  657.             statusOffset = n;
  658.             if (moved)
  659.                 RepairStatus(x1 - statusOffset - 1, moved);
  660.         }
  661.         else
  662.             XBell(display, 0);
  663.     }
  664.     else if (key == XK_Right)
  665.     {
  666.         if (cursor < strlen(status))
  667.         {
  668.             ++cursor;
  669.             x1 = LEFTMARGIN + 3 + XTextWidth(pStatusFontInfo, status, cursor);
  670.             x2 = status_width - RIGHTMARGIN - 4;
  671.             n = (x1 > x2 ? x1 - x2 : 0);
  672.             moved = ( (n == statusOffset) ? 0 : 1);
  673.             statusOffset = n;
  674.             if (moved)
  675.                 RepairStatus(x1 - statusOffset - XTextWidth(pStatusFontInfo, status+cursor-1, 1), moved);
  676.         }
  677.         else
  678.             XBell(display, 0);
  679.     }
  680.     if (!moved && was != cursor)
  681.     {
  682.         rect.x = x = LEFTMARGIN + 2;
  683.         rect.y = y = StatusTop + StatusFontOffset; 
  684.         rect.width = w = status_width - (LEFTMARGIN + RIGHTMARGIN + 4);
  685.         rect.height = h = 2 + charheight;
  686.         XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  687.         XSetForeground(display, status_gc, statusColor);
  688.         r = XTextWidth(pStatusFontInfo, status, was);
  689.         XFillRectangle(display, win, status_gc, x+1+r - statusOffset, y, 1, h);
  690.         XSetForeground(display, status_gc, strikeColor);
  691.         r = XTextWidth(pStatusFontInfo, status, cursor);
  692.         XFillRectangle(display, win, status_gc, x+1+r - statusOffset, y, 1, h);
  693.     }
  694. }
  695. void Announce(char *args, ...)
  696. {
  697.     va_list ap;
  698.     char buf[512];
  699.     if (initialised)
  700.     {
  701.         va_start(ap, args);
  702.         vsprintf(buf, args, ap);
  703.         va_end(ap);
  704.         SetStatusString(buf);
  705.         XFlush(display);
  706.     }
  707.     else
  708.     {
  709.         va_start(ap, args);
  710.         vsprintf(buf, args, ap);
  711.         va_end(ap);
  712.         SetStatusString(buf);
  713.     }
  714.     /* howcome 16/10/94: moved the following statments outside block */
  715.     if (STATUS_TRACE)
  716. fprintf(stderr, "%sn", buf);
  717. }
  718. void Warn(char *args, ...)
  719. {
  720.     va_list ap;
  721.     char buf[512];
  722.     if (initialised)
  723.     {
  724.         va_start(ap, args);
  725.         vsprintf(buf, args, ap);
  726.         va_end(ap);
  727.         if (STATUS_TRACE)
  728.             fprintf(stderr, "%sn", buf);
  729.         SetStatusString(buf);
  730.         XBell(display, 0);
  731.         XFlush(display);
  732.     }
  733.     else
  734.     {
  735.         va_start(ap, args);
  736.         vsprintf(buf, args, ap);
  737.         va_end(ap);
  738.         SetStatusString(buf);
  739.         fprintf(stderr, "%sn", buf);
  740.     }
  741. }
  742. void Beep()
  743. {
  744.     XBell(display, 0);
  745.     XFlush(display);
  746. }
  747. int StatusButtonDown(int button, int px, int py)
  748. {
  749.     char *s;
  750.     int x, y, n;
  751.     unsigned int w, h;
  752.     XRectangle rect;
  753.     x = abButton.x;
  754.     y = abButton.y;
  755.     w = abButton.w;
  756.     h = abButton.h;
  757.     rect.x = x;
  758.     rect.y = y;
  759.     rect.width = w;
  760.     rect.height = h;
  761. #ifdef SELECTION
  762.     /* howcome 1/8/94 */
  763.     if (button == Button1 && !OpenURL /* && !AbortButton */)
  764.     {
  765.       textWidth = XTextWidth(pStatusFontInfo, " ", 1);
  766.       if (textWidth > 0) {
  767. startSelect = (px - 50 - 4) / textWidth; /* 50 should be a define */
  768. /* startSelect = min(startSelect,strlen(status));*/
  769. if (startSelect >= 0) { 
  770.   beginChr = endChr = startSelect;
  771.   selecting = True;
  772. }
  773.       }
  774. /*      fprintf(stderr,"%d down x %d y %d px %d py %d w %d h %dn",startSelect,x,y,px,py,w,h);*/
  775.     }
  776. #endif
  777.     if (button == Button1 && AbortButton &&
  778.         x <= px &&
  779.         px < x + w &&
  780.         y <= py &&
  781.         py < y + h)
  782.     {
  783.         ABup = 0;
  784.         XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  785.         DrawInSet(win, status_gc, x, y, w, h);
  786.         return STATUS;
  787.     }
  788.     /* now check for middle or right button down over status window */
  789.     x = LEFTMARGIN + 2;
  790.     y = StatusTop + StatusFontOffset; 
  791.     w = status_width - (LEFTMARGIN + RIGHTMARGIN + 4);
  792.     h = statusHeight - 12;
  793.     if ((button == Button2 || button == Button3) && LabelString(&n) &&
  794.         x <= px &&
  795.         px < x + w &&
  796.         y <= py &&
  797.         py < y + h)
  798.     {
  799.         s = XFetchBytes(display, &n);
  800. s = strtok(s,"n"); /* howcome 24/5/95: remove newlines */
  801. n = strlen(s);
  802.         if (s)
  803.         {
  804.             x = strlen(status);
  805.             if (x + n > STATSIZ-1)
  806.                 n = STATSIZ-1-x;
  807.             strncpy(status+x, s, n);
  808.             status[x+n] = '';
  809.             cursor = x+n;
  810.  
  811.             XFree(s);
  812.             Redraw(x, y, w, h);
  813.         }
  814.     }
  815. #ifdef SELECTION
  816.     return STATUS; /* howcome 1/8/94: indicate interest in buttonup since user may select (part of) url */
  817. #else
  818.     return VOID;
  819. #endif
  820. }
  821. void HideAuthorizeWidget(void)
  822. {
  823.     AbortButton = 0;
  824.     Authorize = 0;
  825.     busy = 0;
  826.     ClearStatus();
  827.     DisplayStatusBar();
  828.     DisplaySizeChanged(0);
  829.     DisplayScrollBar();
  830.     DisplayDoc(WinLeft, WinTop, WinWidth, WinHeight);
  831.     XFlush(display);
  832. }
  833. void StatusButtonUp(int px, int py)
  834. {
  835.     int x, y;
  836.     unsigned int w, h;
  837.     XRectangle rect;
  838.     x = abButton.x;
  839.     y = abButton.y;
  840.     w = abButton.w;
  841.     h = abButton.h;
  842.     rect.x = x;
  843.     rect.y = y;
  844.     rect.width = w;
  845.     rect.height = h;
  846.     if (AbortButton)
  847.     {
  848.         /* redraw button in up state */
  849.         if (ABup == 0)
  850.         {
  851.             ABup = 1;
  852.             XSetClipRectangles(display, status_gc, 0, 0, &rect, 1, Unsorted);
  853.             DrawOutSet(win, status_gc, x, y, w, h);
  854.         }
  855.         /* check if up event occurs in button */
  856.         if (x <= px &&
  857.             px < x + w &&
  858.             y <= py &&
  859.             py < y + h)
  860.         {
  861.             AbortFlag = 1;
  862.             if (Authorize)  /* hide password widget */
  863.                 HideAuthorizeWidget();
  864.         }
  865.     }
  866. #ifdef SELECTION
  867.     if (selecting) { /* howcome 1/8/94 */
  868.       char *s;
  869.       const int n = strlen(status);
  870.       
  871.       if (beginChr > n && endChr > n) { /* off bounds, select everything */
  872. beginChr = 0;
  873. endChr = strlen(status);
  874.       }
  875.       if (beginChr == endChr && beginChr < n) {
  876. char *pb, *pe;
  877. pb = pe = status + beginChr; /* search for sensible strings */
  878. while(pb >= status && *pb != ':' && *pb !='/')
  879.   pb--;
  880. pb++;
  881. while(*pe != '' && *pe != ':' && *pe !='/')
  882.   pe++;
  883.   
  884. beginChr = pb - status;
  885. endChr = pe - status;
  886.       }
  887.       if (beginChr > endChr) { /* this happens to be true when a ':' of '/' has been pressed, select everything */
  888. beginChr = 0;
  889. endChr = n;
  890.       }
  891.       endChr = min(n, endChr); /* howcome 8/3/95 */
  892.       s = strdup(status);
  893.       strncpy(s, status + beginChr, endChr - beginChr);
  894.       s[endChr-beginChr] = '';
  895.       if (STATUS_TRACE) 
  896. fprintf(stderr,"Set selection: "%s"n",s);
  897.       DisplayStatusBar();
  898.       SetSelection(s);
  899.       Free(s);
  900.       selecting = False;
  901.     }
  902. #endif /* SELECTION */
  903. }
  904. void ShowAbortButton(int n)
  905. {
  906.     AbortFlag = 0;
  907.     AbortButton = n;
  908.     AbortButtonChanged = 1;
  909. }
  910. /* reconfigure status bar to ask for authorisation
  911.    mode is REMOTE for remote hosts, and GATEWAY for the gateway */
  912. void GetAuthorization(int mode, char *host)
  913. {
  914.     Authorize = mode;
  915.     busy = 1;
  916.     ClearStatus();
  917.     ShowAbortButton(1);
  918.     if (mode == GATEWAY)
  919.     {
  920.         strcpy(authreq, "Enter name:password for gateway ");
  921.         strncpy(authreq+32, host, STATSIZ-33);
  922.     }
  923.     else
  924.     {
  925.         strcpy(authreq, "Enter name:password for ");
  926.         strncpy(authreq+24, host, STATSIZ-25);
  927.     }
  928.     authreq[STATSIZ-1] = '';
  929.     if (user)
  930.         sprintf(status, "%s:", user);
  931.     else {
  932.         status[0] = '';
  933. #ifdef SELCTION
  934. beginChr = endChr = 0; /* howcome */
  935. #endif
  936.     }
  937.     cursor = strlen(status);
  938.     if (initialised)
  939.     {
  940.         DisplayStatusBar();
  941.         DisplaySizeChanged(0);
  942.         DisplayScrollBar();
  943.     }
  944.     else
  945.         DisplaySizeChanged(0);
  946. }
  947. /* extract name from "name:password" */
  948. char *UserName(char *who)
  949. {
  950.     char *p;
  951.     static char name[32];
  952.     strncpy(name, who, 30);
  953.     name[31] = '';
  954.     p = strchr(name, ':');
  955.     if (p)
  956.         *p = '';
  957.     return name;
  958. }
  959. /* extract password from "name:password" */
  960. char *PassStr(char *who)
  961. {
  962.     char *p;
  963.     p = strchr(who, ':');
  964.     return (p ? p+1 : "");
  965. }