home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / ncftp-2.4.2-MIHS / src / Win.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-27  |  23.1 KB  |  1,241 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(void)
  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.     int 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 = (int) strlen(l);
  509.         if (llen > maxx - 1)
  510.             llen = maxx - 1;
  511.         rlen = (int) strlen(r);
  512.         if (rlen > maxx - 1)
  513.             rlen = maxx - 1;
  514.         clen = (int) 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, (size_t) 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, (size_t) rmax);
  530.                 }
  531.         } else {
  532.                 /* Do the left side. */    
  533.                 memcpy(bar, l, (size_t) 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, (size_t) 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, (size_t) 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.     int extraLines;
  642.  
  643.     if (multi != 0) {
  644.         if (gSkipToEnd == 1)
  645.             return;
  646.         /* Don't wait between pages if they are redialing.  We don't
  647.          * want to page the site's connect message if redialing is
  648.          * turned on.
  649.          */
  650.         if (gRedialModeEnabled != 0)
  651.             multi = 0;
  652.     }
  653.  
  654.     endp = buf;
  655.     startp = buf;
  656.  
  657.     while (1) {
  658.         if (*startp == '\0')
  659.             break;
  660.         haveCR = 0;
  661.         haveNL = 0;
  662.         for (endp = startp; ; endp++) {
  663.             if (*endp == '\0') {
  664.                 endp = NULL;
  665.                 break;
  666.             } else if (*endp == '\n') {
  667.                 haveNL = 1;
  668.                 *endp = '\0';
  669.                 break;
  670.             } else if (*endp == '\r') {
  671.                 /* Have to do CRs manually because
  672.                  * some systems don't do 'em.  (AIX).
  673.                  */
  674.                 haveCR = 1;
  675.                 *endp = '\0';
  676.                 break;
  677.             }
  678.         }
  679.  
  680.         /* Take long lines that wrap into account. */
  681.         extraLines = endp == startp ? 0 : (endp - startp - 1) / gScreenWidth;
  682.         gCurRow += extraLines;
  683.         if ((multi) && (gCurRow >= gLastRow) && (!gSkipToEnd) && (!haveCR)) {
  684.             wnoutrefresh(gListWin);
  685.             sprintf(pr, "--Page %d--", (++gPageNum));
  686.             MakeBottomLine(pr, kReverse, 0);
  687.             doupdate();
  688.             cbreak();
  689.             c = mvwgetch(gInputWin, 0, 0);
  690.             nocbreak();
  691.             if (c == 'q') {
  692.                 gSkipToEnd = 1;
  693.                 gCurRow = 0;
  694.                 gPendingNL = 1;
  695.                 break;
  696.             }
  697.             gCurRow = extraLines;
  698.         }
  699.         
  700.         if (gPendingNL) {
  701.             waddch(gListWin, '\n');
  702.         }
  703.  
  704.         /* Weird things happened if I did wprintw(gListWin, "%s", startp). */
  705.         waddstr(gListWin, startp);
  706.  
  707.         /* May need to gCurRow++ if line wraps around other side... */
  708.         if (haveNL) {
  709.             gCurRow++;
  710.         } else if (haveCR) {
  711.             getyx(gListWin, y, x);
  712.             wmove(gListWin, y, 0);
  713.         }
  714.         gPendingNL = haveNL;
  715.         if (endp == NULL)
  716.             break;
  717.         startp = endp + 1;
  718.     }
  719. }    /* PrintToListWindow */
  720. #endif    /* USE_CURSES */
  721.  
  722.  
  723.  
  724.  
  725. /* Prints a message, if you have debbuging mode turned on. */
  726.  
  727. /*VARARGS*/
  728. #ifndef HAVE_STDARG_H
  729. void DebugMsg(va_alist)
  730.     va_dcl
  731. #else
  732. void DebugMsg(char *fmt0, ...)
  733. #endif
  734. {
  735.     va_list ap;
  736.     char *fmt;
  737.  
  738. #ifndef HAVE_STDARG_H
  739.     va_start(ap);
  740.     fmt = va_arg(ap, char *);
  741. #else
  742.     va_start(ap, fmt0);
  743.     fmt = fmt0;
  744. #endif
  745.  
  746.     if (gDebug == kDebuggingOn) {
  747.         if (gWinInit) {
  748. #ifdef USE_CURSES
  749.             strcpy(gSprintfBuf, "#DB# ");
  750.             (void) vsprintf(gSprintfBuf + 5, fmt, ap);
  751.             PrintToListWindow(gSprintfBuf, 0);
  752. #endif    /* USE_CURSES */
  753.         } else {
  754.             (void) fprintf(kDebugStream, "#DB# ");
  755.             (void) vfprintf(kDebugStream, fmt, ap);
  756.             (void) fflush(kDebugStream);
  757.         }
  758.     }
  759.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  760.         (void) fprintf(gTraceLogFile, "#DB# ");
  761.         (void) vfprintf(gTraceLogFile, fmt, ap);
  762.         (void) fflush(gTraceLogFile);
  763.     }
  764.     va_end(ap);
  765. }    /* DebugMsg */
  766.  
  767.  
  768.  
  769.  
  770. /* This is similar to DebugMsg, but only writes to the debug log
  771.  * file.  This is useful for putting messages in the log that
  772.  * shouldn't show up on screen (i.e. would make a mess in visual
  773.  * mode.
  774.  */
  775.  
  776. /*VARARGS*/
  777. #ifndef HAVE_STDARG_H
  778. void TraceMsg(va_alist)
  779.     va_dcl
  780. #else
  781. void TraceMsg(char *fmt0, ...)
  782. #endif
  783. {
  784.     va_list ap;
  785.     char *fmt;
  786.  
  787. #ifndef HAVE_STDARG_H
  788.     va_start(ap);
  789.     fmt = va_arg(ap, char *);
  790. #else
  791.     va_start(ap, fmt0);
  792.     fmt = fmt0;
  793. #endif
  794.  
  795.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  796.         (void) fprintf(gTraceLogFile, "#TR# ");
  797.         (void) vfprintf(gTraceLogFile, fmt, ap);
  798.         (void) fflush(gTraceLogFile);
  799.     }
  800.     va_end(ap);
  801. }    /* TraceMsg */
  802.  
  803.  
  804.  
  805.  
  806. /* Prints to our own standard output stream. */
  807.  
  808. /*VARARGS*/
  809. #ifndef HAVE_STDARG_H
  810. void PrintF(va_alist)
  811.     va_dcl
  812. #else
  813. void PrintF(char *fmt0, ...)
  814. #endif
  815. {
  816.     va_list ap;
  817.     char *fmt;
  818.  
  819. #ifndef HAVE_STDARG_H
  820.     va_start(ap);
  821.     fmt = va_arg(ap, char *);
  822. #else
  823.     va_start(ap, fmt0);
  824.     fmt = fmt0;
  825. #endif
  826.  
  827.     /* If it's an important message, don't use this function, use
  828.      * EPrintF() instead.
  829.      */
  830.     if (gVerbosity > kErrorsOnly) {
  831.         if ((gWinInit) && (gRealStdout == gStdout)) {
  832. #ifdef USE_CURSES
  833.             (void) vsprintf(gSprintfBuf, fmt, ap);
  834.             PrintToListWindow(gSprintfBuf, 0);
  835. #endif    /* USE_CURSES */
  836.         } else {
  837.             (void) vsprintf(gSprintfBuf, fmt, ap);
  838.             (void) write(gStdout, gSprintfBuf, strlen(gSprintfBuf));
  839.         }
  840.     }
  841.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  842.         (void) vfprintf(gTraceLogFile, fmt, ap);
  843.         (void) fflush(gTraceLogFile);
  844.     }
  845.     va_end(ap);
  846. }    /* PrintF */
  847.  
  848.  
  849.  
  850. /*VARARGS*/
  851. #ifndef HAVE_STDARG_H
  852. void BoldPrintF(va_alist)
  853.     va_dcl
  854. #else
  855. void BoldPrintF(char *fmt0, ...)
  856. #endif
  857. {
  858.     va_list ap;
  859.     char *fmt;
  860.  
  861. #ifndef HAVE_STDARG_H
  862.     va_start(ap);
  863.     fmt = va_arg(ap, char *);
  864. #else
  865.     va_start(ap, fmt0);
  866.     fmt = fmt0;
  867. #endif
  868.  
  869.     if (gVerbosity > kErrorsOnly) {
  870.         if ((gWinInit) && (gRealStdout == gStdout)) {
  871. #ifdef USE_CURSES
  872.             (void) vsprintf(gSprintfBuf, fmt, ap);
  873.             WAttr(gListWin, kBold, 1);
  874.             PrintToListWindow(gSprintfBuf, 0);
  875.             WAttr(gListWin, kBold, 0);
  876. #endif    /* USE_CURSES */
  877.         } else {
  878.             (void) vsprintf(gSprintfBuf, fmt, ap);
  879.             (void) write(gStdout, gSprintfBuf, strlen(gSprintfBuf));
  880.         }
  881.     }
  882.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  883.         (void) vfprintf(gTraceLogFile, fmt, ap);
  884.         (void) fflush(gTraceLogFile);
  885.     }
  886.     va_end(ap);
  887. }    /* BoldPrintF */
  888.  
  889.  
  890.  
  891.  
  892. /* Prints to stderr. */
  893.  
  894. /*VARARGS*/
  895. #ifndef HAVE_STDARG_H
  896. void EPrintF(va_alist)
  897.     va_dcl
  898. #else
  899. void EPrintF(char *fmt0, ...)
  900. #endif
  901. {
  902.     va_list ap;
  903.     char *fmt;
  904.     char *cp;
  905.  
  906. #ifndef HAVE_STDARG_H
  907.     va_start(ap);
  908.     fmt = va_arg(ap, char *);
  909. #else
  910.     va_start(ap, fmt0);
  911.     fmt = fmt0;
  912. #endif
  913.  
  914.     if (gVerbosity > kQuiet) {
  915.         if (gWinInit) {
  916. #ifdef USE_CURSES
  917.             (void) vsprintf(gSprintfBuf, fmt, ap);
  918.             PrintToListWindow(gSprintfBuf, 0);
  919.             
  920.             /* No buffering on error stream. */
  921.             wnoutrefresh(gListWin);
  922.             doupdate();
  923. #endif    /* USE_CURSES */
  924.         } else {
  925.             (void) vfprintf(stderr, fmt, ap);
  926.         }
  927.     }
  928.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  929.         /* Special hack so when progress meters use \r's we don't
  930.          * print them in the trace file.
  931.          */
  932.         (void) vsprintf(gSprintfBuf, fmt, ap);
  933.         for (cp = gSprintfBuf; ; ) {
  934.             /* Replace all carriage returns with newlines. */
  935.             cp = strchr(cp, '\r');
  936.             if (cp == NULL)
  937.                 break;
  938.             *cp++ = '\n';
  939.         }
  940.         fputs(gSprintfBuf, gTraceLogFile);
  941.         (void) fflush(gTraceLogFile);
  942.     }
  943.     va_end(ap);
  944. }    /* EPrintF */
  945.  
  946.  
  947.  
  948.  
  949.  
  950. /*VARARGS*/
  951. #ifndef HAVE_STDARG_H
  952. void Error(va_alist)
  953.     va_dcl
  954. #else
  955. void Error(int pError0, char *fmt0, ...)
  956. #endif
  957. {
  958.     va_list ap;
  959.     char *fmt;
  960.     int pError;
  961.     longstring buf2;
  962.     
  963. #ifndef HAVE_STDARG_H
  964.     va_start(ap);
  965.     pError = va_arg(ap, int);
  966.     fmt = va_arg(ap, char *);
  967. #else
  968.     va_start(ap, fmt0);
  969.     fmt = fmt0;
  970.     pError = pError0;
  971. #endif
  972.  
  973.     if (gVerbosity > kQuiet) {
  974.         if (gWinInit) {
  975. #ifdef USE_CURSES
  976.             (void) vsprintf(gSprintfBuf, fmt, ap);
  977.             if (gDebug == kDebuggingOn)
  978.                 sprintf(buf2, "Error(%d): ", errno);
  979.             else
  980.                 STRNCPY(buf2, "Error: ");
  981.             STRNCAT(buf2, gSprintfBuf);
  982. #ifdef HAVE_STRERROR
  983.             if ((pError == kDoPerror) && (errno > 0)) {
  984.                 STRNCAT(buf2, "Reason: ");
  985.                 STRNCAT(buf2, strerror(errno));
  986.                 STRNCAT(buf2, "\n");
  987.             }
  988. #endif    /* HAVE_STRERROR */
  989.             PrintToListWindow(buf2, 0);
  990. #endif    /* USE_CURSES */
  991.         } else {
  992.             (void) fprintf(stderr, "Error");
  993.             if (gDebug == kDebuggingOn)
  994.                 (void) fprintf(stderr, "(%d)", errno);
  995.             (void) fprintf(stderr, ": ");
  996.             (void) vfprintf(stderr, fmt, ap);
  997.             (void) fflush(stderr);
  998.             if ((pError == kDoPerror) && (errno > 0))
  999.                 perror("Reason");
  1000.         }
  1001.     }
  1002.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  1003.         (void) fprintf(gTraceLogFile, "Error(%d): ", errno);
  1004.         (void) vfprintf(gTraceLogFile, fmt, ap);
  1005. #ifdef HAVE_STRERROR
  1006.         if ((pError == kDoPerror) && (errno > 0))
  1007.             (void) fprintf(gTraceLogFile, "Reason: %s\n", strerror(errno));
  1008. #endif
  1009.         (void) fflush(gTraceLogFile);
  1010.     }
  1011.     va_end(ap);
  1012. }    /* Error */
  1013.  
  1014.  
  1015.  
  1016.  
  1017. void MultiLineInit(void)
  1018. {
  1019. #ifdef USE_CURSES
  1020.     int maxy, maxx;
  1021.  
  1022.     if (gWinInit) {
  1023.         gCurRow = 0;
  1024.         getmaxyx(gListWin, maxy, maxx);
  1025.         gLastRow = maxy;
  1026.         gSkipToEnd = 0;
  1027.         gPageNum = 0;
  1028.         gMultiLineMode = 1;
  1029.     }
  1030. #endif    /* USE_CURSES */
  1031. }    /* MultiLineInit */
  1032.  
  1033.  
  1034.  
  1035. /*VARARGS*/
  1036. #ifndef HAVE_STDARG_H
  1037. void MultiLinePrintF(va_alist)
  1038.     va_dcl
  1039. #else
  1040. void MultiLinePrintF(char *fmt0, ...)
  1041. #endif
  1042. {
  1043.     va_list ap;
  1044.     char *fmt;
  1045.  
  1046. #ifndef HAVE_STDARG_H
  1047.     va_start(ap);
  1048.     fmt = va_arg(ap, char *);
  1049. #else
  1050.     va_start(ap, fmt0);
  1051.     fmt = fmt0;
  1052. #endif
  1053.  
  1054.     if (gVerbosity > kErrorsOnly) {
  1055.         if ((gWinInit) && (gRealStdout == gStdout)) {
  1056. #ifdef USE_CURSES        
  1057.             (void) vsprintf(gSprintfBuf, fmt, ap);
  1058.             PrintToListWindow(gSprintfBuf, 1);
  1059. #endif    /* USE_CURSES */
  1060.         } else {
  1061.             (void) vsprintf(gSprintfBuf, fmt, ap);
  1062.             (void) write(gStdout, gSprintfBuf, strlen(gSprintfBuf));
  1063.         }
  1064.     }
  1065.     if ((gTrace == kTracingOn) && (gTraceLogFile != NULL)) {
  1066.         (void) vfprintf(gTraceLogFile, fmt, ap);
  1067.         (void) fflush(gTraceLogFile);
  1068.     }
  1069.  
  1070.     va_end(ap);
  1071. }    /* MultiLinePrintF */
  1072.  
  1073.  
  1074.  
  1075.  
  1076. void MakeBottomLine(char *pr, int flags, int addTail)
  1077. {
  1078. #ifdef USE_CURSES
  1079.     int len;
  1080.     int doCreate;
  1081.     int maxy, maxx;
  1082.  
  1083.     len = (int) strlen(pr);
  1084.     if (addTail)
  1085.         len += strlen(kPromptTail);
  1086.     else if (flags & kReverse)
  1087.         len++;    /* Will add a space so you can see cursor. */
  1088.  
  1089.     doCreate = 0;
  1090.     if (gPromptWin != NULL) {
  1091.         getmaxyx(gPromptWin, maxy, maxx);
  1092.         if (maxx != len) {
  1093.             delwin(gPromptWin);
  1094.             delwin(gInputWin);
  1095.             doCreate = 1;
  1096.         }
  1097.     } else {
  1098.         doCreate = 1;
  1099.     }
  1100.  
  1101.     if (doCreate) {
  1102.         gPromptWin = newwin(1, len, LINES - 1, 0);
  1103.         gInputWin = newwin(1, COLS - len, LINES - 1, len);
  1104.  
  1105.         if ((gPromptWin == NULL) || (gInputWin == NULL))
  1106.             Exit(kExitWinFail2);
  1107.     }
  1108.  
  1109.     werase(gPromptWin);
  1110.     WAttr(gPromptWin, flags, 1);
  1111.     if (addTail) {
  1112.         mvwprintw(gPromptWin, 0,0, "%s%s", pr, kPromptTail);
  1113.         WAttr(gPromptWin, flags, 0);
  1114.     } else {
  1115.         mvwprintw(gPromptWin, 0,0, "%s", pr);
  1116.         WAttr(gPromptWin, flags, 0);
  1117.     }
  1118.     wnoutrefresh(gPromptWin);
  1119.     werase(gInputWin);
  1120.     touchwin(gInputWin);
  1121.     wnoutrefresh(gInputWin);
  1122.     doupdate();
  1123. #endif    /* USE_CURSES */
  1124. }    /* MakeBottomLine */
  1125.  
  1126.  
  1127.  
  1128.  
  1129. void SetPrompt(char *pr)
  1130. {
  1131.     string p;
  1132.  
  1133.     if ((pr == kUseDefaultPrompt)
  1134.         || STREQ(pr, kLineModePrompt)
  1135.         || STREQ(pr, kVisualModePrompt)) {
  1136.         if (gWinInit)
  1137.             STRNCPY(p, kVisualModePrompt);
  1138.         else
  1139.             STRNCPY(p, kLineModePrompt);
  1140.     } else {
  1141.         STRNCPY(p, pr);
  1142.     }
  1143.     STRNCPY(gPrompt, p);
  1144. #ifdef USE_CURSES
  1145.     if (gWinInit)
  1146.         MakeBottomLine(p, kBold, 1);
  1147. #endif    /* USE_CURSES */
  1148. }    /* SetPrompt */
  1149.  
  1150.  
  1151.  
  1152. #ifdef USE_CURSES
  1153. /* Draws a string centered in a window. */
  1154. void WAddCenteredStr(WINDOW *w, int y, char *str)
  1155. {
  1156.     int x;
  1157.     int maxy, maxx;
  1158.  
  1159.     getmaxyx(w, maxy, maxx);
  1160.     x = (maxx - strlen(str)) / 2;
  1161.     if (x < 0)
  1162.         x = 0;
  1163.     wmove(w, y, x);
  1164.     waddstr(w, str);
  1165. }    /* WAddCenteredStr */
  1166. #endif    /* USE_CURSES */
  1167.  
  1168.  
  1169.  
  1170.  
  1171. void InitWindows(void)
  1172. {
  1173.     char *cp;
  1174.     int on;
  1175. #ifdef USE_CURSES
  1176.     int maxx, maxy;
  1177. #endif
  1178.  
  1179.     on = gVisualMode && gIsToTTY && gIsFromTTY;
  1180.  
  1181. #ifdef USE_CURSES
  1182.     if (on) {
  1183.         initscr();
  1184.         if (stdscr == NULL)
  1185.             goto fail;
  1186.         gWinInit = 1;
  1187.         SIGNAL(SIGTERM, SigTerm);
  1188.  
  1189.         nl();
  1190.  
  1191.         gPromptWin = gInputWin = NULL;
  1192.         gListWin = newwin(LINES - 2, COLS, 0, 0);
  1193.         gBarWin = newwin(1, COLS, LINES - 2, 0);
  1194.  
  1195.         if ((gListWin == NULL) || (gBarWin == NULL))
  1196.             Exit(kExitWinFail1);
  1197.  
  1198.         scrollok(gListWin, TRUE);
  1199.         idlok(gListWin, TRUE);
  1200.         wmove(gListWin, 0, 0);
  1201.         noecho();    /* Leave this off until we need it. */
  1202.  
  1203.         WAttr(gBarWin, kReverse, 1);
  1204.  
  1205.         getmaxyx(gListWin, maxy, maxx);
  1206.         gScreenWidth = maxx;
  1207.  
  1208.         gBarLeft[0] = '\0';
  1209.         gBarCenter[0] = '\0';
  1210.         gBarRight[0] = '\0';
  1211.  
  1212.         LoadHistory();
  1213.  
  1214.         /* Probably not set yet, unless you specified a host on
  1215.          * the command line.
  1216.          */
  1217.         SetScreenInfo();
  1218. #ifdef SIGTSTP
  1219.         if (SIGNAL(SIGTSTP, SIG_IGN) != SIG_IGN) {
  1220.             SIGNAL(SIGTSTP, SigTStp);
  1221.             SIGNAL(SIGCONT, SigTStp);
  1222.         }
  1223. #endif
  1224.         return;
  1225.     }
  1226. fail:
  1227. #endif    /* USE_CURSES */
  1228.     gWinInit = 0;
  1229.  
  1230.     cp = (char *) getenv("COLUMNS");
  1231.     if (cp != NULL)
  1232.         gScreenWidth = atoi(cp);
  1233.  
  1234.     /* Prompt will already be set if connected. */
  1235.     if (gConnected == 0)
  1236.         SetPrompt(kUseDefaultPrompt);
  1237. }    /* InitWindows */
  1238.  
  1239. /* eof */
  1240.  
  1241.