home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncftp-2.3.0-src.tgz / tar.out / contrib / ncftp / Win.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  23KB  |  1,237 lines

  1. /* Win.c */
  2.  
  3. #include "Sys.h"
  4. #include "Curses.h"
  5.  
  6. #include <errno.h>
  7. #include <signal.h>
  8. #include <stdlib.h>
  9.  
  10. #include "Util.h"
  11. #include "Main.h"
  12. #include "Version.h"
  13. #include "Bookmark.h"
  14. #include "RCmd.h"
  15. #include "LGets.h"
  16. #include "GetPass.h"
  17.  
  18.  
  19. #ifdef USE_CURSES
  20.  
  21. #include "WGets.h"
  22.  
  23. extern int endwin(void);
  24. extern long gEventNumber;
  25. WINDOW *gListWin;
  26. WINDOW *gInputWin;
  27. WINDOW *gPromptWin;
  28. WINDOW *gBarWin;
  29. int gCurRow, gLastRow, gSkipToEnd;
  30. int gPageNum;
  31. int gMultiLineMode = 0;
  32. int gPendingNL = 0;
  33. int gBackgroundProcessing = 0;
  34. int gUsingDefaultBar = 0;
  35. int gUsingTmpCenterBar = 0;
  36. string gBarLeft, gBarCenter, gBarRight;
  37.  
  38. /* Other protos, whose parameters aren't WINDOW *ptrs, are in Win.h */
  39. void WAddCenteredStr(WINDOW *, int, char *);
  40. void WAttr(WINDOW *w, int attr, int on);
  41.  
  42. extern WINDOW *gPrefsWin, *gHostWin;
  43.  
  44. #endif    /* USE_CURSES */
  45.  
  46. string gPrompt = kLineModePrompt;
  47. int gWinInit = 0;
  48. char *gSprintfBuf = NULL;
  49. int gScreenWidth = 80;
  50.  
  51. extern longstring gRemoteCWD;
  52. extern longstring gLockFileName;
  53. extern int gConnected, gVerbosity;
  54. extern Bookmark gRmtInfo;
  55. extern string gHost;
  56. extern int gStdout, gRealStdout, gOtherSessionRunning;
  57. extern FILE *gTraceLogFile;
  58. extern int gDebug, gTrace;
  59. extern LineList gCmdHistory;
  60. extern int gVisualMode, gIsToTTY, gIsFromTTY, gStartup;
  61. extern int gRedialModeEnabled;
  62.  
  63.  
  64. void EndWin(void)
  65. {
  66.     if (gWinInit) {
  67.         gWinInit = 0;
  68. #ifdef USE_CURSES
  69.         if (gEventNumber > 0L) {
  70.             clear();
  71.             refresh();
  72.         }
  73.         endwin();
  74. #endif    /* USE_CURSES */
  75.     }
  76. }    /* EndWin */
  77.  
  78.  
  79.  
  80.  
  81. void Exit(int exitStatus)
  82. {
  83.     if (gOtherSessionRunning == 0) {
  84.         (void) UNLINK(gLockFileName);
  85.     }
  86.     EndWin();
  87.     exit(exitStatus);
  88. }    /* Exit */
  89.  
  90.  
  91.  
  92. static void
  93. SigTerm(int sigNum)
  94. {
  95.     Exit(kExitSignal);
  96. }    /* SigTerm */
  97.  
  98.  
  99.  
  100.  
  101. void SaveScreen(void)
  102. {
  103. #ifdef USE_CURSES
  104.     if (gWinInit) {
  105.         /* Clearing the screen is necessary
  106.          * because ncurses doesn't move the
  107.          * cursor to the bottom left.
  108.          *
  109.          * This also causes the restore
  110.          * operation to require that we paint
  111.          * all our windows by hand, because we
  112.          * have just left the screen blank so
  113.          * when refresh gets called in the
  114.          * restore it just returns the screen
  115.          * to blank.
  116.          *
  117.          * If it weren't for this screen clear,
  118.          * we would be able to get away with
  119.          * just doing an endwin(), the shell,
  120.          * and then a refresh() without us
  121.          * re-drawing any windows manually.
  122.          */
  123.         clear();
  124.         refresh();
  125.          endwin();
  126.         fflush(stdout);
  127.         fflush(stderr);
  128.     }
  129. #endif    /* USE_CURSES */
  130. }    /* SaveScreen */
  131.  
  132.  
  133.  
  134. static void TTYWaitForReturn(void)
  135. {
  136.     int tty;
  137.     int junk;
  138.  
  139.     tty = open("/dev/tty", O_RDWR);
  140.     if (tty != -1) {
  141.         write(tty, "[Hit return]", 12);
  142.         read(tty, &junk, 1);
  143.         close(tty);
  144.     }
  145. }    /* TTYWaitForReturn */
  146.  
  147.  
  148.  
  149. void RestoreScreen(int pressKey)
  150. {
  151. #ifdef USE_CURSES
  152.     if (gWinInit) {
  153.         if (pressKey) {
  154. #    if (CURSES_SHELL_BUG == 0)
  155.             TTYWaitForReturn();
  156. #    else
  157.             sleep(2);
  158. #    endif
  159.         }
  160.         refresh();
  161.         UpdateScreen(1);
  162.     }
  163. #endif    /* USE_CURSES */
  164. }    /* RestoreScreen */
  165.  
  166.  
  167.  
  168. void Beep(int on)
  169. {
  170.     static time_t lastBeepTime = 0;
  171.     time_t now;
  172.  
  173.     time(&now);
  174.  
  175.     /* Don't flood the user with beeps. Once per two seconds is reasonable. */
  176.     if ((on > 0) && ((int) (now - lastBeepTime) > 1)) {
  177. #ifdef USE_CURSES
  178.         if (gWinInit)
  179.             beep();
  180.         else
  181. #endif
  182.         {
  183.             fprintf(stderr, "\007");    /* ^G */
  184.             fflush(stderr);
  185.         }
  186.     }
  187.     lastBeepTime = now;
  188. }    /* Beep */
  189.  
  190.  
  191.  
  192.  
  193. #ifdef USE_CURSES
  194. /* Many old curses libraries don't support wattron() and its attributes.
  195.  * They should support wstandout() though.  This routine is an attempt
  196.  * to use the best substitute available, depending on what the curses
  197.  * library has.
  198.  */
  199. void WAttr(WINDOW *w, int attr, int on)
  200. {
  201.     /* Define PLAIN_TEXT_ONLY if you have the attributes, but don't want
  202.      * to use them.
  203.      */
  204. #ifndef PLAIN_TEXT_ONLY
  205. #ifdef A_REVERSE
  206.     if (attr & kReverse) {
  207.         if (on)
  208.             wattron(w, A_REVERSE);
  209.         else
  210.             wattroff(w, A_REVERSE);
  211.     }
  212. #else
  213.     if (attr & kReverse) {
  214.         if (on)
  215.             wstandout(w);
  216.         else
  217.             wstandend(w);
  218.  
  219.         /* Nothing else will be done anyway, so just return now. */
  220.         return;
  221.     }
  222. #endif    /* A_REVERSE */
  223.  
  224. #ifdef A_BOLD
  225.     if (attr & kBold) {
  226.         if (on)
  227.             wattron(w, A_BOLD);
  228.         else
  229.             wattroff(w, A_BOLD);
  230.     }
  231. #else
  232.     /* Do nothing.  Plain is best substitute. */
  233. #endif    /* A_BOLD */
  234.  
  235. #ifdef A_UNDERLINE
  236.     if (attr & kUnderline) {
  237.         if (on)
  238.             wattron(w, A_UNDERLINE);
  239.         else
  240.             wattroff(w, A_UNDERLINE);
  241.     }
  242. #else
  243.     /* Try using standout mode in place of underline. */
  244.     if (attr & kUnderline) {
  245.         if (on)
  246.             wstandout(w);
  247.         else
  248.             wstandend(w);
  249.  
  250.         /* Nothing else will be done anyway, so just return now. */
  251.         return;
  252.     }
  253. #endif    /* A_UNDERLINE */
  254.  
  255. #ifdef A_DIM
  256.     if (attr & kDim) {
  257.         if (on)
  258.             wattron(w, A_DIM);
  259.         else
  260.             wattroff(w, A_DIM);
  261.     }
  262. #else
  263.     /* Do nothing.  Plain is best substitute. */
  264. #endif    /* A_DIM */
  265.  
  266. #ifdef A_NORMAL
  267.     if (attr == kNormal) {
  268.         wattrset(w, A_NORMAL);
  269.         return;
  270.     }
  271. #else
  272.     /* At least make sure standout mode is off. */
  273.     if (attr == kNormal) {
  274.         wstandend(w);
  275.         return;
  276.     }
  277. #endif    /* A_NORMAL */
  278. #endif    /* PLAIN_TEXT_ONLY */
  279. }    /* WAttr */
  280. #endif    /* USE_CURSES */
  281.  
  282.  
  283.  
  284.  
  285. void UpdateScreen(int wholeScreen)
  286. {
  287. #ifdef USE_CURSES
  288.     if (gWinInit) {
  289.         if (wholeScreen) {
  290.             touchwin(gListWin);
  291.             touchwin(gBarWin);
  292.             touchwin(gPromptWin);
  293.             touchwin(gInputWin);
  294.                 
  295.             wnoutrefresh(gListWin);
  296.             wnoutrefresh(gBarWin);
  297.             wnoutrefresh(gPromptWin);
  298.             wnoutrefresh(gInputWin);
  299.         }
  300.         doupdate();
  301.     }
  302. #endif    /* USE_CURSES */
  303. }    /* UpdateScreen */
  304.  
  305.  
  306.  
  307. void FlushListWindow(void)
  308. {
  309. #ifdef USE_CURSES
  310.     if (gWinInit) {
  311.         wnoutrefresh(gListWin);
  312.         doupdate();
  313.         return;
  314.     }
  315. #endif    /* USE_CURSES */
  316.     fflush(stdout);
  317.     fflush(stderr);        /* Overkill, since stderr _should_ be unbuffered. */
  318. }    /* FlushListWindow */
  319.  
  320.  
  321.  
  322.  
  323. #ifdef USE_CURSES
  324. #ifdef SIGTSTP
  325. static
  326. void SigTStp(int sigNum)
  327. {
  328. /* TO-DO: (doesn't work 100% correctly yet) */
  329.     if (sigNum == SIGTSTP) {
  330.         if ((gPrefsWin != NULL) || (gHostWin != NULL)) {
  331.             /* Doing this with these windows open can cause problems. */
  332.             return;
  333.         }
  334.         SaveScreen();
  335.         TraceMsg("SIGTSTP: Suspended.\n");
  336.         SIGNAL(SIGTSTP, SIG_DFL);
  337.         kill(getpid(), SIGSTOP);    /* Send stop signal to ourselves. */
  338.     } else {
  339.         SIGNAL(SIGTSTP, SigTStp);
  340.         SIGNAL(SIGCONT, SigTStp);
  341.         if (sigNum == SIGCONT) {
  342.             TraceMsg("SIGCONT: Resumed.\n");
  343.         } else {
  344.             TraceMsg("SIG %d.\n", sigNum);
  345.         }
  346.         if (InForeGround())
  347.             RestoreScreen(0);
  348.         else
  349.             gBackgroundProcessing = 1;
  350.     }
  351. }    /* SigTStp */
  352. #endif
  353. #endif    /* USE_CURSES */
  354.  
  355.  
  356.  
  357.  
  358.  
  359. /* Read a line of input, and axe the end-of-line. */
  360. char *Gets(char *str, size_t size)
  361. {
  362.     string pr;
  363. #ifdef USE_CURSES
  364.     int result;
  365.     WGetsParams wgp;
  366.     int maxy, maxx;
  367. #endif    /* USE_CURSES */    
  368.  
  369. #ifdef USE_CURSES
  370.     if (gWinInit) {
  371.         /* Background processing only gets turned on if you use ^Z
  372.          * from within the program and then "bg" it.  We assume that
  373.          * when you do that, you want to get a "tty output" message
  374.          * when the operation finishes.  Note that you wouldn't get
  375.          * gBackgroundProcessing == 1 if you did "ncftp &" because
  376.          * you would never get to the part that turns it on (the ^Z
  377.          * handler).
  378.          */
  379.         if (gBackgroundProcessing) {
  380.             /* Want to give you a "stopped - tty output" message in
  381.              * your shell when we get here.
  382.              */
  383.             PrintF("\nBackground processing has finished.\n");
  384.             FlushListWindow();
  385.             while (! InForeGround())
  386.                 sleep(1);
  387.             gBackgroundProcessing = 0;
  388.             RestoreScreen(0);
  389.         }
  390.  
  391.         str[0] = '\0';
  392.         wnoutrefresh(gListWin);
  393.         if (gMultiLineMode) {
  394.             SetPrompt(gPrompt);
  395.             gMultiLineMode = 0;
  396.         } else {
  397.             werase(gInputWin);
  398.             wnoutrefresh(gInputWin);
  399.         }
  400.         SetScreenInfo();
  401.         doupdate();
  402.         wgp.w = gInputWin;
  403.         wgp.sy = 0;
  404.         wgp.sx = 0;
  405.  
  406.         getmaxyx(gInputWin, maxy, maxx);
  407.         wgp.fieldLen = maxx - 1;
  408.         wgp.dst = str;
  409.         wgp.dstSize = size;
  410.         wgp.useCurrentContents = 0;
  411.         wgp.echoMode = wg_RegularEcho;
  412.         wgp.history = &gCmdHistory;
  413.         result = wg_Gets(&wgp);
  414.         if (result < 0)
  415.             return (NULL);    /* Error, or EOF. */
  416.         return (str);
  417.     } else
  418. #endif    /* USE_CURSES */
  419.     {
  420.         Echo(stdin, 1);        /* Turn echo on, if it wasn't already. */
  421.         STRNCPY(pr, gPrompt);
  422.         STRNCAT(pr, kPromptTail);
  423.         return LineModeGets(pr, str, size);
  424.     }
  425. }    /* Gets */
  426.  
  427.  
  428.  
  429.  
  430. void GetAnswer(char *prompt, char *answer, size_t siz, int noEcho)
  431. {
  432. #ifdef USE_CURSES
  433.     WGetsParams wgp;
  434.     int maxy, maxx;
  435. #endif
  436.  
  437.     PTRZERO(answer, siz);
  438. #ifdef USE_CURSES
  439.     if (gWinInit) {
  440.         wnoutrefresh(gListWin);
  441.         MakeBottomLine(prompt, kReverse, 0);
  442.         doupdate();
  443.         wgp.w = gInputWin;
  444.         wgp.sy = 0;
  445.         wgp.sx = 0;
  446.         getmaxyx(gInputWin, maxy, maxx);
  447.         wgp.fieldLen = maxx - 1;
  448.         wgp.dst = answer;
  449.         wgp.dstSize = siz;
  450.         wgp.useCurrentContents = 0;
  451.         wgp.echoMode = noEcho ? wg_BulletEcho : wg_RegularEcho;
  452.         wgp.history = wg_NoHistory;
  453.         wg_Gets(&wgp);
  454.         return;
  455.     }
  456. #endif    /* USE_CURSES */
  457.     if (noEcho)
  458.         GetPass(prompt, answer, siz);
  459.     else {
  460.         StdioGets(prompt, answer, siz);
  461.     }
  462. }    /* GetAnswer */
  463.  
  464.  
  465.  
  466.  
  467. void SetBar(char *l, char *c, char *r, int doUp, int tmpCenter)
  468. {
  469. #ifdef USE_CURSES
  470.     int maxy, maxx;
  471.     int i;
  472.     int rmax;
  473.     size_t llen, rlen, clen;
  474.     string bar;
  475.     string barTmp;
  476.  
  477.     if (gWinInit) {
  478.         if (l == NULL)
  479.             l = gBarLeft;
  480.         else if (doUp != -1)
  481.             STRNCPY(gBarLeft, l);    
  482.  
  483.         if (r == NULL)
  484.             r = gBarRight;
  485.         else if (doUp != -1)
  486.             STRNCPY(gBarRight, r);    
  487.  
  488.         if (c == NULL) {
  489.             c = gBarCenter;
  490.     /*        if (gUsingDefaultBar == 1) {
  491.                 *c = '\0';
  492.                 gUsingDefaultBar = 0;
  493.             } else */ if (gUsingTmpCenterBar == 1) {
  494.                 *c = '\0';
  495.                 gUsingTmpCenterBar = 0;
  496.             }
  497.         } else {
  498.             STRNCPY(gBarCenter, c);    
  499.             gUsingTmpCenterBar = 0;
  500.             if (tmpCenter)
  501.                 gUsingTmpCenterBar = 1;
  502.         }
  503.  
  504.         getmaxyx(gBarWin, maxy, maxx);
  505.         for (i=0; i<maxx; i++)
  506.             bar[i] = ' ';
  507.  
  508.         llen = strlen(l);
  509.         if (llen > maxx - 1)
  510.             llen = maxx - 1;
  511.         rlen = strlen(r);
  512.         if (rlen > maxx - 1)
  513.             rlen = maxx - 1;
  514.         clen = strlen(c);
  515.         if (clen > maxx - 1)
  516.             clen = maxx - 1;
  517.  
  518.         if /* (rlen + (clen/2) > (maxx/2)) */
  519.             ((2*rlen) + (clen) > (maxx))
  520.         {
  521.                 /* Put the center part on the left so we can see it. */
  522.                 memcpy(bar, c, clen);
  523.             
  524.                 /* Do the right side. */    
  525.                 rmax = maxx - 1 - clen;
  526.                 if (rmax > 0) {
  527.                     AbbrevStr(barTmp, r, (size_t) rmax, 0);
  528.                     rmax = strlen(barTmp);
  529.                     memcpy(bar + maxx - rmax, r, rmax);
  530.                 }
  531.         } else {
  532.                 /* Do the left side. */    
  533.                 memcpy(bar, l, llen);
  534.  
  535.                 /* Do the middle. */    
  536.                 if (*c != '\0') {
  537.                     rlen = maxx - 1;
  538.                     AbbrevStr(barTmp, c, (size_t) rlen, 0);
  539.                     rlen = strlen(barTmp);
  540.                     memcpy(bar + (maxx - 1 - rlen) / 2, barTmp, rlen);
  541.                 }
  542.             
  543.                 /* Do the right side. */    
  544.                 rmax = maxx - 1 - llen;
  545.                 if (rmax > 0) {
  546.                     AbbrevStr(barTmp, r, (size_t) rmax, 0);
  547.                     rmax = strlen(barTmp);
  548.                     memcpy(bar + maxx - rmax, r, rmax);
  549.                 }
  550.         }
  551.  
  552.         bar[maxx] = '\0';
  553.         
  554.         wmove(gBarWin, 0, 0);
  555.         waddstr(gBarWin, bar);
  556.  
  557.         if (doUp == 0)    
  558.             wnoutrefresh(gBarWin);
  559.         else
  560.             wrefresh(gBarWin);
  561.     }
  562. #endif    /* USE_CURSES */
  563. }    /* SetBar */
  564.  
  565.  
  566.  
  567.  
  568. void SetDefaultBar(void)
  569. {
  570. #ifdef USE_CURSES
  571.     string str;
  572.  
  573.     if (gWinInit) {
  574.         STRNCPY(str, "NcFTP ");
  575.         STRNCAT(str, kVersion);
  576.         STRNCAT(str, " by Mike Gleason, NCEMRSoft (mgleason@probe.net).");
  577.         gUsingDefaultBar = 1;
  578.  
  579.         SetBar("", str, "", 0, 0);
  580.     } else {
  581.         SetPrompt(kUseDefaultPrompt);
  582.     }
  583. #else
  584.     SetPrompt(kUseDefaultPrompt);
  585. #endif
  586. }    /* SetDefaultBar */
  587.  
  588.  
  589.  
  590.  
  591. void SetScreenInfo(void)
  592. {
  593.     string pr;
  594.     string pcwd;
  595.     char *cp;
  596.     int len, len2;
  597.     size_t maxPCwdLen;
  598.  
  599.     MakeStringPrintable(pcwd, (unsigned char *) gRemoteCWD, sizeof(pcwd));
  600.     if (gWinInit) {
  601.         if (gConnected) {
  602.             maxPCwdLen = gScreenWidth - strlen(gRmtInfo.name) - 2;
  603.             AbbrevStr(pr, pcwd, maxPCwdLen, 0);
  604.             SetBar(gRmtInfo.name, NULL, pr, 0, 0);
  605.             SetPrompt(gRmtInfo.bookmarkName);
  606.         } else {
  607.             SetDefaultBar();
  608.             SetPrompt(kUseDefaultPrompt);
  609.         }
  610.     } else {
  611.         if (gConnected) {
  612.             STRNCPY(pr, gRmtInfo.bookmarkName);
  613.             STRNCAT(pr, ":");
  614.             len = (int) strlen(pr);
  615.             len2 = (int) strlen(pcwd);
  616.             if (len + len2 > kPromptLimit) {
  617.                 STRNCAT(pr, "...");
  618.                 cp = pcwd + len2 - (kPromptLimit - len - 3);
  619.                 STRNCAT(pr, cp);
  620.             } else {
  621.                 STRNCAT(pr, pcwd);
  622.             }
  623.             SetPrompt(pr);
  624.         } else {
  625.             SetPrompt(kUseDefaultPrompt);
  626.         }
  627.     }
  628. }    /* SetScreenInfo */
  629.  
  630.  
  631.  
  632.  
  633. #ifdef USE_CURSES
  634. void PrintToListWindow(char *buf, int multi)
  635. {
  636.     char *endp, *startp;
  637.     int c, haveNL;
  638.     int haveCR;
  639.     int y, x;
  640.     string pr;
  641.  
  642.     if (multi != 0) {
  643.         if (gSkipToEnd == 1)
  644.             return;
  645.         /* Don't wait between pages if they are redialing.  We don't
  646.          * want to page the site's connect message if redialing is
  647.          * turned on.
  648.          */
  649.         if (gRedialModeEnabled != 0)
  650.             multi = 0;
  651.     }
  652.  
  653.     endp = buf;
  654.     startp = buf;
  655.  
  656.     while (1) {
  657.         if (*startp == '\0')
  658.             break;
  659.         haveCR = 0;
  660.         haveNL = 0;
  661.         for (endp = startp; ; endp++) {
  662.             if (*endp == '\0') {
  663.                 endp = NULL;
  664.                 break;
  665.             } else if (*endp == '\n') {
  666.                 haveNL = 1;
  667.                 *endp = '\0';
  668.                 break;
  669.             } else if (*endp == '\r') {
  670.                 /* Have to do CRs manually because
  671.                  * some systems don't do 'em.  (AIX).
  672.                  */
  673.                 haveCR = 1;
  674.                 *endp = '\0';
  675.                 break;
  676.             }
  677.         }
  678.         if ((multi) && (gCurRow >= gLastRow) && (!gSkipToEnd) && (!haveCR)) {
  679.             wnoutrefresh(gListWin);
  680.             sprintf(pr, "--Page %d--", (++gPageNum));
  681.             MakeBottomLine(pr, kReverse, 0);
  682.             doupdate();
  683.             cbreak();
  684.             c = mvwgetch(gInputWin, 0, 0);
  685.             nocbreak();
  686.             if (c == 'q') {
  687.                 gSkipToEnd = 1;
  688.                 gCurRow = 0;
  689.                 gPendingNL = 1;
  690.                 break;
  691.             }
  692.             gCurRow = 0;
  693.         }
  694.         
  695.         if (gPendingNL) {
  696.             waddch(gListWin, '\n');
  697.         }
  698.  
  699.         /* Weird things happened if I did wprintw(gListWin, "%s", startp). */
  700.         waddstr(gListWin, startp);
  701.  
  702.         /* May need to gCurRow++ if line wraps around other side... */
  703.         if (haveNL) {
  704.             gCurRow++;
  705.         } else if (haveCR) {
  706.             getyx(gListWin, y, x);
  707.             wmove(gListWin, y, 0);
  708.         }
  709.         gPendingNL = haveNL;
  710.         if (endp == NULL)
  711.             break;
  712.         startp = endp + 1;
  713.     }
  714. }    /* PrintToListWindow */
  715. #endif    /* USE_CURSES */
  716.  
  717.  
  718.  
  719.  
  720. /* Prints a message, if you have debbuging mode turned on. */
  721.  
  722. /*VARARGS*/
  723. #ifndef HAVE_STDARG_H
  724. void DebugMsg(va_alist)
  725.     va_dcl
  726. #else
  727. void DebugMsg(char *fmt0, ...)
  728. #endif
  729. {
  730.     va_list ap;
  731.     char *fmt;
  732.  
  733. #ifndef HAVE_STDARG_H
  734.     va_start(ap);
  735.     fmt = va_arg(ap, char *);
  736. #else
  737.     va_start(ap, fmt0);
  738.     fmt = fmt0;
  739. #endif
  740.  
  741.     if (gDebug == kDebuggingOn) {
  742.         if (gWinInit) {
  743. #ifdef USE_CURSES
  744.             strcpy(gSprintfBuf, "#DB# ");
  745.             (void) vsprintf(gSprintfBuf + 5, fmt, ap);
  746.             PrintToListWindow(gSprintfBuf, 0);
  747. #endif    /* USE_CURSES */
  748.         } else {
  749.             (void) fprintf(kDebugStream, "#DB# ");
  750.             (void) vfprintf(kDebugStream, fmt, ap);
  751.             (void) fflush(kDebugStream);
  752.         }
  753.     }
  754.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  755.         (void) fprintf(gTraceLogFile, "#DB# ");
  756.         (void) vfprintf(gTraceLogFile, fmt, ap);
  757.         (void) fflush(gTraceLogFile);
  758.     }
  759.     va_end(ap);
  760. }    /* DebugMsg */
  761.  
  762.  
  763.  
  764.  
  765. /* This is similar to DebugMsg, but only writes to the debug log
  766.  * file.  This is useful for putting messages in the log that
  767.  * shouldn't show up on screen (i.e. would make a mess in visual
  768.  * mode.
  769.  */
  770.  
  771. /*VARARGS*/
  772. #ifndef HAVE_STDARG_H
  773. void TraceMsg(va_alist)
  774.     va_dcl
  775. #else
  776. void TraceMsg(char *fmt0, ...)
  777. #endif
  778. {
  779.     va_list ap;
  780.     char *fmt;
  781.  
  782. #ifndef HAVE_STDARG_H
  783.     va_start(ap);
  784.     fmt = va_arg(ap, char *);
  785. #else
  786.     va_start(ap, fmt0);
  787.     fmt = fmt0;
  788. #endif
  789.  
  790.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  791.         (void) fprintf(gTraceLogFile, "#TR# ");
  792.         (void) vfprintf(gTraceLogFile, fmt, ap);
  793.         (void) fflush(gTraceLogFile);
  794.     }
  795.     va_end(ap);
  796. }    /* TraceMsg */
  797.  
  798.  
  799.  
  800.  
  801. /* Prints to our own standard output stream. */
  802.  
  803. /*VARARGS*/
  804. #ifndef HAVE_STDARG_H
  805. void PrintF(va_alist)
  806.     va_dcl
  807. #else
  808. void PrintF(char *fmt0, ...)
  809. #endif
  810. {
  811.     va_list ap;
  812.     char *fmt;
  813.  
  814. #ifndef HAVE_STDARG_H
  815.     va_start(ap);
  816.     fmt = va_arg(ap, char *);
  817. #else
  818.     va_start(ap, fmt0);
  819.     fmt = fmt0;
  820. #endif
  821.  
  822.     /* If it's an important message, don't use this function, use
  823.      * EPrintF() instead.
  824.      */
  825.     if (gVerbosity > kErrorsOnly) {
  826.         if ((gWinInit) && (gRealStdout == gStdout)) {
  827. #ifdef USE_CURSES
  828.             (void) vsprintf(gSprintfBuf, fmt, ap);
  829.             PrintToListWindow(gSprintfBuf, 0);
  830. #endif    /* USE_CURSES */
  831.         } else {
  832.             (void) vsprintf(gSprintfBuf, fmt, ap);
  833.             (void) write(gStdout, gSprintfBuf, strlen(gSprintfBuf));
  834.         }
  835.     }
  836.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  837.         (void) vfprintf(gTraceLogFile, fmt, ap);
  838.         (void) fflush(gTraceLogFile);
  839.     }
  840.     va_end(ap);
  841. }    /* PrintF */
  842.  
  843.  
  844.  
  845. /*VARARGS*/
  846. #ifndef HAVE_STDARG_H
  847. void BoldPrintF(va_alist)
  848.     va_dcl
  849. #else
  850. void BoldPrintF(char *fmt0, ...)
  851. #endif
  852. {
  853.     va_list ap;
  854.     char *fmt;
  855.  
  856. #ifndef HAVE_STDARG_H
  857.     va_start(ap);
  858.     fmt = va_arg(ap, char *);
  859. #else
  860.     va_start(ap, fmt0);
  861.     fmt = fmt0;
  862. #endif
  863.  
  864.     if (gVerbosity > kErrorsOnly) {
  865.         if ((gWinInit) && (gRealStdout == gStdout)) {
  866. #ifdef USE_CURSES
  867.             (void) vsprintf(gSprintfBuf, fmt, ap);
  868.             WAttr(gListWin, kBold, 1);
  869.             PrintToListWindow(gSprintfBuf, 0);
  870.             WAttr(gListWin, kBold, 0);
  871. #endif    /* USE_CURSES */
  872.         } else {
  873.             (void) vsprintf(gSprintfBuf, fmt, ap);
  874.             (void) write(gStdout, gSprintfBuf, strlen(gSprintfBuf));
  875.         }
  876.     }
  877.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  878.         (void) vfprintf(gTraceLogFile, fmt, ap);
  879.         (void) fflush(gTraceLogFile);
  880.     }
  881.     va_end(ap);
  882. }    /* BoldPrintF */
  883.  
  884.  
  885.  
  886.  
  887. /* Prints to stderr. */
  888.  
  889. /*VARARGS*/
  890. #ifndef HAVE_STDARG_H
  891. void EPrintF(va_alist)
  892.     va_dcl
  893. #else
  894. void EPrintF(char *fmt0, ...)
  895. #endif
  896. {
  897.     va_list ap;
  898.     char *fmt;
  899.     char *cp;
  900.  
  901. #ifndef HAVE_STDARG_H
  902.     va_start(ap);
  903.     fmt = va_arg(ap, char *);
  904. #else
  905.     va_start(ap, fmt0);
  906.     fmt = fmt0;
  907. #endif
  908.  
  909.     if (gVerbosity > kQuiet) {
  910.         if (gWinInit) {
  911. #ifdef USE_CURSES
  912.             (void) vsprintf(gSprintfBuf, fmt, ap);
  913.             PrintToListWindow(gSprintfBuf, 0);
  914.             
  915.             /* No buffering on error stream. */
  916.             wnoutrefresh(gListWin);
  917.             doupdate();
  918. #endif    /* USE_CURSES */
  919.         } else {
  920.             (void) vfprintf(stderr, fmt, ap);
  921.         }
  922.     }
  923.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  924.         /* Special hack so when progress meters use \r's we don't
  925.          * print them in the trace file.
  926.          */
  927.         (void) vsprintf(gSprintfBuf, fmt, ap);
  928.         for (cp = gSprintfBuf; ; ) {
  929.             /* Replace all carriage returns with newlines. */
  930.             cp = strchr(cp, '\r');
  931.             if (cp == NULL)
  932.                 break;
  933.             *cp++ = '\n';
  934.         }
  935.         fputs(gSprintfBuf, gTraceLogFile);
  936.         (void) fflush(gTraceLogFile);
  937.     }
  938.     va_end(ap);
  939. }    /* EPrintF */
  940.  
  941.  
  942.  
  943.  
  944.  
  945. /*VARARGS*/
  946. #ifndef HAVE_STDARG_H
  947. void Error(va_alist)
  948.     va_dcl
  949. #else
  950. void Error(int pError0, char *fmt0, ...)
  951. #endif
  952. {
  953.     va_list ap;
  954.     char *fmt;
  955.     int pError;
  956.     longstring buf2;
  957.     
  958. #ifndef HAVE_STDARG_H
  959.     va_start(ap);
  960.     pError = va_arg(ap, int);
  961.     fmt = va_arg(ap, char *);
  962. #else
  963.     va_start(ap, fmt0);
  964.     fmt = fmt0;
  965.     pError = pError0;
  966. #endif
  967.  
  968.     if (gVerbosity > kQuiet) {
  969.         if (gWinInit) {
  970. #ifdef USE_CURSES
  971.             (void) vsprintf(gSprintfBuf, fmt, ap);
  972.             if (gDebug == kDebuggingOn)
  973.                 sprintf(buf2, "Error(%d): ", errno);
  974.             else
  975.                 STRNCPY(buf2, "Error: ");
  976.             STRNCAT(buf2, gSprintfBuf);
  977. #ifdef HAVE_STRERROR
  978.             if ((pError == kDoPerror) && (errno > 0)) {
  979.                 STRNCAT(buf2, "Reason: ");
  980.                 STRNCAT(buf2, strerror(errno));
  981.                 STRNCAT(buf2, "\n");
  982.             }
  983. #endif    /* HAVE_STRERROR */
  984.             PrintToListWindow(buf2, 0);
  985. #endif    /* USE_CURSES */
  986.         } else {
  987.             (void) fprintf(stderr, "Error");
  988.             if (gDebug == kDebuggingOn)
  989.                 (void) fprintf(stderr, "(%d)", errno);
  990.             (void) fprintf(stderr, ": ");
  991.             (void) vfprintf(stderr, fmt, ap);
  992.             (void) fflush(stderr);
  993.             if ((pError == kDoPerror) && (errno > 0))
  994.                 perror("Reason");
  995.         }
  996.     }
  997.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  998.         (void) fprintf(gTraceLogFile, "Error(%d): ", errno);
  999.         (void) vfprintf(gTraceLogFile, fmt, ap);
  1000. #ifdef HAVE_STRERROR
  1001.         if ((pError == kDoPerror) && (errno > 0))
  1002.             (void) fprintf(gTraceLogFile, "Reason: %s\n", strerror(errno));
  1003. #endif
  1004.         (void) fflush(gTraceLogFile);
  1005.     }
  1006.     va_end(ap);
  1007. }    /* Error */
  1008.  
  1009.  
  1010.  
  1011.  
  1012. void MultiLineInit(void)
  1013. {
  1014. #ifdef USE_CURSES
  1015.     int maxy, maxx;
  1016.  
  1017.     if (gWinInit) {
  1018.         gCurRow = 0;
  1019.         getmaxyx(gListWin, maxy, maxx);
  1020.         gLastRow = maxy;
  1021.         gSkipToEnd = 0;
  1022.         gPageNum = 0;
  1023.         gMultiLineMode = 1;
  1024.     }
  1025. #endif    /* USE_CURSES */
  1026. }    /* MultiLineInit */
  1027.  
  1028.  
  1029.  
  1030. /*VARARGS*/
  1031. #ifndef HAVE_STDARG_H
  1032. void MultiLinePrintF(va_alist)
  1033.     va_dcl
  1034. #else
  1035. void MultiLinePrintF(char *fmt0, ...)
  1036. #endif
  1037. {
  1038.     va_list ap;
  1039.     char *fmt;
  1040.  
  1041. #ifndef HAVE_STDARG_H
  1042.     va_start(ap);
  1043.     fmt = va_arg(ap, char *);
  1044. #else
  1045.     va_start(ap, fmt0);
  1046.     fmt = fmt0;
  1047. #endif
  1048.  
  1049.     if (gVerbosity > kErrorsOnly) {
  1050.         if ((gWinInit) && (gRealStdout == gStdout)) {
  1051. #ifdef USE_CURSES        
  1052.             (void) vsprintf(gSprintfBuf, fmt, ap);
  1053.             PrintToListWindow(gSprintfBuf, 1);
  1054. #endif    /* USE_CURSES */
  1055.         } else {
  1056.             (void) vsprintf(gSprintfBuf, fmt, ap);
  1057.             (void) write(gStdout, gSprintfBuf, strlen(gSprintfBuf));
  1058.         }
  1059.     }
  1060.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  1061.         (void) vfprintf(gTraceLogFile, fmt, ap);
  1062.         (void) fflush(gTraceLogFile);
  1063.     }
  1064.  
  1065.     va_end(ap);
  1066. }    /* MultiLinePrintF */
  1067.  
  1068.  
  1069.  
  1070.  
  1071. void MakeBottomLine(char *pr, int flags, int addTail)
  1072. {
  1073. #ifdef USE_CURSES
  1074.     int len;
  1075.     int doCreate;
  1076.     int maxy, maxx;
  1077.  
  1078.     len = (int) strlen(pr);
  1079.     if (addTail)
  1080.         len += strlen(kPromptTail);
  1081.     else if (flags & kReverse)
  1082.         len++;    /* Will add a space so you can see cursor. */
  1083.  
  1084.     doCreate = 0;
  1085.     if (gPromptWin != NULL) {
  1086.         getmaxyx(gPromptWin, maxy, maxx);
  1087.         if (maxx != len) {
  1088.             delwin(gPromptWin);
  1089.             delwin(gInputWin);
  1090.             doCreate = 1;
  1091.         }
  1092.     } else {
  1093.         doCreate = 1;
  1094.     }
  1095.  
  1096.     if (doCreate) {
  1097.         gPromptWin = newwin(1, len, LINES - 1, 0);
  1098.         gInputWin = newwin(1, COLS - len, LINES - 1, len);
  1099.  
  1100.         if ((gPromptWin == NULL) || (gInputWin == NULL))
  1101.             Exit(kExitWinFail2);
  1102.     }
  1103.  
  1104.     WAttr(gPromptWin, flags, 1);
  1105.     if (addTail) {
  1106.         mvwprintw(gPromptWin, 0,0, "%s%s", pr, kPromptTail);
  1107.         WAttr(gPromptWin, flags, 0);
  1108.     } else {
  1109.         mvwprintw(gPromptWin, 0,0, "%s", pr);
  1110.         WAttr(gPromptWin, flags, 0);
  1111.         if (flags & kReverse)
  1112.             wprintw(gPromptWin, " ");
  1113.     }
  1114.     wnoutrefresh(gPromptWin);
  1115.     werase(gInputWin);
  1116.     touchwin(gInputWin);
  1117.     wnoutrefresh(gInputWin);
  1118.     doupdate();
  1119. #endif    /* USE_CURSES */
  1120. }    /* MakeBottomLine */
  1121.  
  1122.  
  1123.  
  1124.  
  1125. void SetPrompt(char *pr)
  1126. {
  1127.     string p;
  1128.  
  1129.     if ((pr == kUseDefaultPrompt)
  1130.         || STREQ(pr, kLineModePrompt)
  1131.         || STREQ(pr, kVisualModePrompt)) {
  1132.         if (gWinInit)
  1133.             STRNCPY(p, kVisualModePrompt);
  1134.         else
  1135.             STRNCPY(p, kLineModePrompt);
  1136.     } else {
  1137.         STRNCPY(p, pr);
  1138.     }
  1139.     STRNCPY(gPrompt, p);
  1140. #ifdef USE_CURSES
  1141.     if (gWinInit)
  1142.         MakeBottomLine(p, kBold, 1);
  1143. #endif    /* USE_CURSES */
  1144. }    /* SetPrompt */
  1145.  
  1146.  
  1147.  
  1148. #ifdef USE_CURSES
  1149. /* Draws a string centered in a window. */
  1150. void WAddCenteredStr(WINDOW *w, int y, char *str)
  1151. {
  1152.     int x;
  1153.     int maxy, maxx;
  1154.  
  1155.     getmaxyx(w, maxy, maxx);
  1156.     x = (maxx - strlen(str)) / 2;
  1157.     if (x < 0)
  1158.         x = 0;
  1159.     wmove(w, y, x);
  1160.     waddstr(w, str);
  1161. }    /* WAddCenteredStr */
  1162. #endif    /* USE_CURSES */
  1163.  
  1164.  
  1165.  
  1166.  
  1167. void InitWindows(void)
  1168. {
  1169.     char *cp;
  1170.     int on;
  1171. #ifdef USE_CURSES
  1172.     int maxx, maxy;
  1173. #endif
  1174.  
  1175.     on = gVisualMode && gIsToTTY && gIsFromTTY;
  1176.  
  1177. #ifdef USE_CURSES
  1178.     if (on) {
  1179.         initscr();
  1180.         if (stdscr == NULL)
  1181.             goto fail;
  1182.         gWinInit = 1;
  1183.         SIGNAL(SIGTERM, SigTerm);
  1184.  
  1185.         nl();
  1186.  
  1187.         gPromptWin = gInputWin = NULL;
  1188.         gListWin = newwin(LINES - 2, COLS, 0, 0);
  1189.         gBarWin = newwin(1, COLS, LINES - 2, 0);
  1190.  
  1191.         if ((gListWin == NULL) || (gBarWin == NULL))
  1192.             Exit(kExitWinFail1);
  1193.  
  1194.         scrollok(gListWin, TRUE);
  1195.         idlok(gListWin, TRUE);
  1196.         wmove(gListWin, 0, 0);
  1197.         noecho();    /* Leave this off until we need it. */
  1198.  
  1199.         WAttr(gBarWin, kReverse, 1);
  1200.  
  1201.         getmaxyx(gListWin, maxy, maxx);
  1202.         gScreenWidth = maxx + 1;
  1203.  
  1204.         gBarLeft[0] = '\0';
  1205.         gBarCenter[0] = '\0';
  1206.         gBarRight[0] = '\0';
  1207.  
  1208.         LoadHistory();
  1209.  
  1210.         /* Probably not set yet, unless you specified a host on
  1211.          * the command line.
  1212.          */
  1213.         SetScreenInfo();
  1214. #ifdef SIGTSTP
  1215.         if (SIGNAL(SIGTSTP, SIG_IGN) != SIG_IGN) {
  1216.             SIGNAL(SIGTSTP, SigTStp);
  1217.             SIGNAL(SIGCONT, SigTStp);
  1218.         }
  1219. #endif
  1220.         return;
  1221.     }
  1222. fail:
  1223. #endif    /* USE_CURSES */
  1224.     gWinInit = 0;
  1225.  
  1226.     cp = (char *) getenv("COLUMNS");
  1227.     if (cp != NULL)
  1228.         gScreenWidth = atoi(cp);
  1229.  
  1230.     /* Prompt will already be set if connected. */
  1231.     if (gConnected == 0)
  1232.         SetPrompt(kUseDefaultPrompt);
  1233. }    /* InitWindows */
  1234.  
  1235. /* eof */
  1236.  
  1237.