home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / top2src.zip / MAIN.C < prev    next >
C/C++ Source or Header  |  2000-07-13  |  15KB  |  401 lines

  1. /******************************************************************************
  2. MAIN.C       Main loop and program entry point.
  3.  
  4.     Copyright 1993 - 2000 Paul J. Sidorsky
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License, version 2, as
  8.     published by the Free Software Foundation.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19. This module contains the program entry point (main() in DOS & OS/2, WinMain()
  20. in Win32) and the main input loop.
  21. ******************************************************************************/
  22.  
  23. #include "top.h"
  24.  
  25. /* main() - Program entry point under DOS and OS/2.
  26.    Parameters:  ac - Number of command line arguments.
  27.                 av - String array of command line arguments.
  28.    Returns:  Nothing.
  29. */
  30. /* WinMain() - Program entry point under Win32.
  31.    Parameters:  hInstance - Handle of this instance of TOP.
  32.                 hPrevInstance - Handle of previous instance of TOP.
  33.                 lpszCmdParam - String of command line parameters.
  34.                 nCmdShow - Numeric code telling how TOP's window should
  35.                            open (normal, minimized, etc.)
  36.    Returns:  Program result code.
  37.    Notes:  This function never returns.  exit() is always used to quit TOP.
  38. */
  39. #ifndef __WIN32__
  40. extern void main(XINT ac, char *av[])
  41. #else
  42. extern int pascal WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  43.                           LPSTR lpszCmdParam, int nCmdShow)
  44. #endif
  45. {
  46.  
  47. /* This function is a little cluttered but it is manageable. */
  48.  
  49. #ifdef __WIN32__
  50. /* TOP doesn't use any of the WinMain parameters. */
  51. (void) hInstance;
  52. (void) hPrevInstance;
  53. (void) lpszCmdParam;
  54. /* OpenDoors needs to know how to show the TOP window. */
  55. od_control.od_cmd_show = nCmdShow;
  56. /* Load TOP's custom icon. */
  57. od_control.od_app_icon = LoadIcon(hInstance, "Icon");
  58. /* Because init() needs a separated command line, it is passed the global
  59.    command line variables provided by the Borland compiler. */
  60. init(_argc, _argv);
  61. #else
  62. /* Initialize TOP. */
  63. init(ac, av);
  64. #endif
  65. /* Show a title page if the option is turned on. */
  66. if (cfg.showtitle)
  67.     {
  68.     show_file("TOPTITLE", SCRN_ALL);
  69.     }
  70. /* Find and load the user, creating a new user if needed. */
  71. search_for_user();
  72. /* Show a news file if the option is on. */
  73. if (cfg.shownews)
  74.     {
  75.     show_file("TOPNEWS", SCRN_ALL);
  76.     }
  77. /* Prepare the screen for dual window mode if the user has it turned on. */
  78. if (user.pref1 & PREF1_DUALWINDOW)
  79.     {
  80.     top_output(OUT_SCREEN, getlang("DWOutputPrepare"));
  81.     top_output(OUT_SCREEN, getlang("DWOutputSetCurPos"));
  82.     }
  83. /* Show the welcome. */
  84. top_output(OUT_SCREEN, getlang("SitDown"));
  85. /* Show who's in the channel and a basic help. */
  86. channelsummary();
  87. /* Let other users know we're here. */
  88. dispatch_message(MSG_ENTRY, user.emessage, -1, 0, 0);
  89. /* Store the screen location under dual window mode. */
  90. if (user.pref1 & PREF1_DUALWINDOW)
  91.     {
  92.     // Different for AVT when I find out what the store/recv codes are.
  93.     od_disp_emu("\x1B" "[s", TRUE);
  94.     }
  95. /* Run the main input loop forever. */
  96. for (;;)
  97.     {
  98.     main_loop();
  99.     }
  100.  
  101. }
  102.  
  103. /* In the main loop, DOS gets the current clock tick from the system to
  104.    help it determine when to timeslice. */
  105. #if !defined(__OS2__) && !defined(__WIN32__)
  106. #define _clock_tick() (*(long XFAR *)0x46cL)
  107. #endif
  108.  
  109. /* main_loop() - Main input loop.
  110.    Parameters:  None.
  111.    Returns:  Nothing.
  112. */
  113. void main_loop(void)
  114. {
  115. XINT key, pos, wwc; /* Input key, string position, word wrap counter. */
  116. unsigned char input[256], ww[81]; /* Input buffer, word wrap buffer. */
  117. XINT tmp; /* Result code. */
  118. #ifndef __OS2__
  119. long clktick; /* Holds the clock tick under DOS. */
  120. #endif
  121.  
  122. /* Initialize variables. */
  123. onflag = 0;
  124. memset(input, 0, MAXSTRLEN + 1); memset(ww, 0, 81);
  125. pos = -1; wwc = 0;
  126. for(;;)
  127.     {
  128. #ifdef __OS2__
  129.     /* Timeslice under OS/2. */
  130. //  od_sleep(0);
  131.     DosSleep(10);
  132. #endif
  133. #if !defined(__OS2__) && !defined(__WIN32__)
  134.     /* Get the clock tick under DOS. */
  135.     clktick = _clock_tick();
  136. #endif
  137.     /* Clear the key input holder. */
  138.     key = '\0';
  139.     /* Set/clear the onflag if the user has started typing. */
  140.     if (strlen(input) > 0)
  141.         {
  142.         onflag = 1;
  143.         }
  144.     else
  145.         {
  146.         onflag = 0;
  147.         }
  148.     /* If the position is -1 then the screen needs to be initialized. */
  149.     if (pos == -1)
  150.         {
  151.         /* Clear/initalize the screen in dual window mode. */
  152.         if (onflag && !(user.pref1 & PREF1_DUALWINDOW))
  153.             {
  154.             top_output(OUT_SCREEN, getlang("InputPrefix"));
  155.             } // Also time, date, minleft to bottom
  156.         /* More dual window mode preparation. */
  157.         if (user.pref1 & PREF1_DUALWINDOW)
  158.             {
  159.             if (onflag)
  160.                 {
  161.                 /* Prepare the screen when the user is typing. */
  162.                 // Next four lines are here temporarily!
  163.                 // These will get replaced when proper scrolling is done
  164.                 top_output(OUT_SCREEN, getlang("DWPrepareInput"));
  165.                 top_output(OUT_SCREEN, getlang("DWTopDisplay"));
  166.                 top_output(OUT_SCREEN, getlang("DWMiddleDisplay"));
  167.                 top_output(OUT_SCREEN, getlang("DWBottomDisplay"));
  168.                 top_output(OUT_SCREEN, getlang("DWInputCurPos"));
  169.                 /* Prepares the scren to "retype" what the user has already
  170.                    input. */
  171.                 top_output(OUT_SCREEN, getlang("DWRestoreInput"));
  172.                 }
  173.             else
  174.                 {
  175.                 /* Prepare the scren when the user is idle. */
  176.                 // Next four lines are here temporarily!
  177.                 top_output(OUT_SCREEN, getlang("DWPrepareInput"));
  178.                 top_output(OUT_SCREEN, getlang("DWTopDisplay"));
  179.                 top_output(OUT_SCREEN, getlang("DWMiddleDisplay"));
  180.                 top_output(OUT_SCREEN, getlang("DWBottomDisplay"));
  181.                 top_output(OUT_SCREEN, getlang("DWInputCurPos"));
  182.                 }
  183.             }
  184.         else
  185.             {
  186.             /* Show the prompt in normal mode. */
  187.             top_output(OUT_SCREEN, getlang("DefaultPrompt"), user.handle);
  188.             }
  189.         /* Clear the position counter. */
  190.         pos = 0;
  191.         if (onflag) // Temp for DW mode.
  192.             {
  193.             /* If the user has typing, "retype" what the user has already
  194.                input. */
  195.             pos = strlen(input);
  196.             /* We don't want codes to be processed when retyping. */
  197.             outproclang = FALSE; outproccol = FALSE;
  198.             top_output(OUT_SCREEN, input);
  199.             outproclang = TRUE; outproccol = TRUE;
  200.             /* In dual window mode, clear the onflag.  This is done because
  201.                during message processing, the onflag is used to display the
  202.                interrupt string, but the interrupt string is unnecessary
  203.                in dual window mode. */
  204.             if (user.pref1 & PREF1_DUALWINDOW)
  205.                 {
  206.                 onflag = 0;
  207.                 }
  208.             }
  209.         }
  210.  
  211.     /* Show messages only if the user isn't typing, or if the user has
  212.        block while typing turned off. */
  213.     if (pos == 0 || (pos > 0 && !(user.pref1 & PREF1_BLKWHILETYP)))
  214.         {
  215.         /* Only poll for messages once enough time has elapsed. */
  216.         if ((((float) myclock() - (float) lastpoll) / (float) CLK_TCK) >=
  217.             POLLTIMEDELAY)
  218.             {
  219.             /* Poker operations, unused. */
  220. /*//|            if ((((float) myclock() - (float) lastpokerpoll) /
  221.                    (float) CLK_TCK) >=
  222.                    ((float) cfg.pokerpolltime / 10.0))
  223.                 {
  224.                 XINT pokd;
  225.  
  226.                 for (pokd = 0; pokd < cfg.pokermaxgames; pokd++)
  227.                     {
  228.                     if (pokeringame[pokd])
  229.                         {
  230.                         poker_eventkernel(pokd);
  231.                         }
  232.                     }
  233.                 lastpokerpoll = myclock();
  234.                 }*///|
  235.             /* Store the screen location.  This is no longer used but was
  236.                left in so it could be used later. */
  237.             if (pos > 0)
  238.                 {
  239.                 ystore = wherey();
  240.                 xstore = wherex();
  241.                 }
  242.             /* Process incoming messages.  Only delete the name if the user
  243.                isn't typing, which is what the parameter indicates. */
  244.             tmp = process_messages(pos == 0 ? TRUE : FALSE);
  245.             /* If the result is greater than one, at least one message was
  246.                processed. */
  247.             if (tmp > 0)
  248.                 {
  249.                 /* pos is set to -1 to tell the next run of the loop that
  250.                    the screen needs to be restored. */
  251.                 pos = -1;
  252.                 /* onflag used to be set down here but it works better
  253.                    when set at the start of the loop. */
  254. /*                if (strlen(input) > 0)
  255.                     {
  256.                     onflag = 1;
  257.                     }*/
  258.                 }
  259.             if (tmp < 1)
  260.                 {
  261.                 /* If no messages were processed, check for any BBS
  262.                    pages. */
  263.                 if (cfg.bbstype != BBS_UNKNOWN && bbs_call_processmsgs)
  264.                     {
  265.                     tmp = (*bbs_call_processmsgs)();
  266.                     }
  267.                 if (tmp > 0)
  268.                     {
  269.                     /* Tell the next loop to restore the screen. */
  270.                     pos = -1;
  271.                     }
  272.                 }
  273.             /* Set the last polling time. */
  274.             lastpoll = myclock();
  275.             }
  276.         }
  277.     /* Only get a keypress if the screen is ready. */
  278.     if (pos != -1)
  279.            {
  280.         /* Check if any keys have been pressed, without waiting for one. */
  281.         key = od_get_key(FALSE);
  282.         }
  283.     /* Process the key if one was pressed. */
  284.     if (key)
  285.            {
  286.         /* Backspace (also delete). */
  287.         if (key == 8 || key == 127)
  288.                {
  289.             /* Only backspace if the user has typed something. */
  290.             if (pos > 0)
  291.                 {
  292.                 /* Clear the last character and move back the position
  293.                    counter. */
  294.                 input[--pos] = '\0';
  295.                 /* Display a destructive backspace. */
  296.                 od_disp_str("\b \b");
  297.                 /* Clear the last character in the word wrap buffer if there
  298.                    is one. */
  299.                 if (wwc > 0)
  300.                     {
  301.                     ww[--wwc] = '\0';
  302.                     }
  303.                 }
  304.             continue;
  305.             }
  306.         /* ENTER (or RETURN). */
  307.         if (key == 13)
  308.             {
  309.             /* Trim trailing spaces from the input, which users can use to
  310.                annoy people. */
  311.             trim_string(input, input, NO_LTRIM);
  312.             /* Process the input. */
  313.             process_input(input);
  314.             /* Save the screen position in dual window mode. */
  315.             if (user.pref1 & PREF1_DUALWINDOW)
  316.                 {
  317.                 // Different for AVT when I find out what the store/recv codes are.
  318.                 od_disp_emu("\x1B" "[s", TRUE);
  319.                 }
  320.             /* Tell the next loop the screen needs restoring. */
  321.             pos = -1;
  322.             /* Reset the buffers and word wrap counter. */
  323.             memset(input, 0, MAXSTRLEN + 1);
  324.             memset(ww, 0, 81);
  325.             wwc = 0;
  326.             continue;
  327.             }
  328.         /* Displayable characters.  Only process if the string isn't too
  329.            long. */
  330.         if (key >= 32 && key <= MAXASCII &&
  331.             pos < MAXSTRLEN)
  332.             {
  333.             /* Store this keypress in the input buffer. */
  334.             input[pos++] = key;
  335.             input[pos] = '\0';
  336.             /* Display the key directly. */
  337.             od_putch(key);
  338.             /* Store the keypress in the word wrap buffer. */
  339.             ww[wwc++] = key;
  340.             ww[wwc] = '\0';
  341.             /* Space, hyphen, and slash are considered the word break
  342.                characters. */
  343.             if (key == ' ' || key == '-' || key == '/')
  344.                 {
  345.                 /* Clear the word wrap buffers. */
  346.                 wwc = 0;
  347.                 memset(ww, 0, 81);
  348.                 }
  349.             if (wherex() != 80)
  350.                 {
  351.                 /* If the cursor isn't at the end of the screen, nothing
  352.                    more needs to be done. */
  353.                 continue;
  354.                 }
  355.             else
  356.                 {
  357.                 /* End of line reached, perform word wrap. */
  358.                 XINT xwc; /* Backspace counter. */
  359.  
  360.                 /* Only wrap if the current word is less than 50 characters
  361.                    long.  Otherwise it can be slow and annoying to the user. */
  362.                 if (wwc < 50)
  363.                     {
  364.                     /* Backspace out the last word. */
  365.                     for (xwc = 0; xwc < wwc; xwc++)
  366.                         {
  367.                         od_disp_str("\b \b");
  368.                         }
  369.                     }
  370.                 /* Jump to the next line. */
  371.                 od_disp_str("\r\n");
  372.                 /* Redisplay the last word if it's not too long. */
  373.                 if (wwc < 50)
  374.                     {
  375.                     od_disp_str(ww);
  376.                     }
  377.                 /* Clear the word wrap buffer and reset the counter. */
  378.                 memset(ww, 0, 81);
  379.                 wwc = 0;
  380.                 continue;
  381.                 }
  382.             }
  383.         }
  384. /* Timeslicing is only done under DOS. */
  385. #if !defined(__OS2__) && !defined(__WIN32__)
  386.     else
  387.         {
  388.         /* Timeslice if a key wasn't pressed and if the clock tick has
  389.            changed.  Waiting for the next clock tick prevents TOP from
  390.            completely surrendering control of the CPU, which would make
  391.            input hideously slow. */
  392.         if (!key || _clock_tick() != clktick)
  393.             {
  394.             od_sleep(0);
  395.             }
  396.         }
  397. #endif
  398.     }
  399.  
  400. }
  401.