home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / clipper / nettos11.zip / MSGSERV / BMODE.PRG next >
Text File  |  1993-02-23  |  11KB  |  368 lines

  1. /*
  2.  * File......: BMODE.PRG
  3.  * Author....: Glenn Scott
  4.  * CIS ID....: 71620,1521
  5.  * Date......: $Date$
  6.  * Revision..: $Revision$
  7.  * Log file..: $Logfile$
  8.  * 
  9.  * This is an original work by Glenn Scott and is placed in the
  10.  * public domain.
  11.  *
  12.  * Modification history:
  13.  * ---------------------
  14.  *
  15.  * $Log$
  16.  *
  17.  */
  18.  
  19.  
  20. #include "ftint86.ch"
  21. #include "netto.ch"
  22.  
  23. #define GET_BMODE      4
  24.  
  25.  
  26. /*  $DOC$
  27.  *  $FUNCNAME$
  28.  *     FN_SETBMOD()
  29.  *  $CATEGORY$
  30.  *     Message
  31.  *  $ONELINER$
  32.  *     Set broadcast mode
  33.  *  $SYNTAX$
  34.  *
  35.  *     fn_setBMod( <nTargetMode> ) -> nMode
  36.  *
  37.  *  $ARGUMENTS$
  38.  *
  39.  *     <nTargetMode> is one of:
  40.  *
  41.  *       0    Servers store user and server messages sent to this station.
  42.  *            Shell retrieves & displays message.
  43.  *
  44.  *       1    Shell displays server messages; discards user messages
  45.  *
  46.  *       2    Server stores server messages; discards user messages;
  47.  *            shell won't display the message (app must poll for it)
  48.  *
  49.  *       3    Server stores server and user messages but shell doesn't
  50.  *            display; app must poll for messages
  51.  *
  52.  *  $RETURNS$
  53.  *
  54.  *       The resulting message mode after attempting to set to the 
  55.  *       target mode. (See "Arguments")
  56.  *
  57.  *  $DESCRIPTION$
  58.  *     
  59.  *  $EXAMPLES$
  60.  *
  61.  *  $INCLUDE$
  62.  *
  63.  *  $SEEALSO$
  64.  *     FN_GETBMOD()
  65.  *  $END$
  66.  */
  67.  
  68. function fn_setbmod( nMode )
  69.   local aRegs[ INT86_MAX_REGS ]
  70.  
  71.   default nMode to 0
  72.  
  73.   aRegs[AX]        := makehi( 222 )               // DEh 
  74.   aRegs[DX]        := nMode
  75.  
  76.   _fnSetErr( iif( ft_int86( INT21, aRegs ), ESUCCESS, EINT86 ) )
  77.   return lowbyte( aRegs[ AX ] )
  78.  
  79.  
  80. /*  $DOC$
  81.  *  $FUNCNAME$
  82.  *     FN_GETBMOD()
  83.  *  $CATEGORY$
  84.  *     Message
  85.  *  $ONELINER$
  86.  *     Get broadcast mode
  87.  *  $SYNTAX$
  88.  *
  89.  *     fn_getBMod() -> nMode
  90.  *
  91.  *  $ARGUMENTS$
  92.  *
  93.  *     None
  94.  *
  95.  *  $RETURNS$
  96.  *
  97.  *     <nMode>, one of:
  98.  *
  99.  *       0    Servers store user and server messages sent to this station
  100.  *            Shell retrieves & displays message.
  101.  *
  102.  *       1    Shell displays server messages; discards user messages
  103.  *
  104.  *       2    Server stores server messages; discards user messages;
  105.  *            shell won't display the message (app must poll for it)
  106.  *
  107.  *       3    Server stores server and user messages but shell doesn't
  108.  *            display; app must poll for messages
  109.  *
  110.  *  $DESCRIPTION$
  111.  *     
  112.  *  $EXAMPLES$
  113.  *
  114.  *  $INCLUDE$
  115.  *
  116.  *  $SEEALSO$
  117.  *     FN_SETBMOD()
  118.  *  $END$
  119.  */
  120.  
  121.  
  122. function fn_getbmod()
  123.   return fn_setbmod( GET_BMODE )
  124.  
  125.  
  126. /*  $DOC$
  127.  *  $FUNCNAME$
  128.  *     OVERVIEW
  129.  *  $CATEGORY$
  130.  *     Message
  131.  *  $ONELINER$
  132.  *     Message services overview
  133.  *  $SYNTAX$
  134.  *
  135.  *  $ARGUMENTS$
  136.  *
  137.  *  $RETURNS$
  138.  *
  139.  *  $DESCRIPTION$
  140.  *     
  141.  *    This is a really simple API, mostly because some of the calls
  142.  *    aren't implemented in NETTO because they're old and Novell
  143.  *    doesn't support them anymore.  For further information on 
  144.  *    the complete API, consult a reference like Novell's documentation
  145.  *    or Charles Rose's _Programmer's Guide to NetWare_ (McGraw-Hill).
  146.  *
  147.  *    However, the ones that remain are useful, and have to do 
  148.  *    with Broadcast Messages.
  149.  *
  150.  *    Broadcast messages are those annoying one-liners that show up
  151.  *    on the bottom of a NetWare user's screen.  They're usually 
  152.  *    55 bytes or less and require the user to hit Control-Enter to
  153.  *    clear.  
  154.  *
  155.  *    In Windows, the NWPOPUP.EXE utility intercepts those broadcast
  156.  *    messages and displays them in a window.
  157.  *
  158.  *    There are two sorts of broadcast messages: those that come from
  159.  *    the server and those that come from other users.  The manner
  160.  *    in which the user receives these different types of messages
  161.  *    is determined by the shell's _broadcast mode_. Netto allows
  162.  *    you complete control over getting and setting the broadcast mode.
  163.  *    See FN_GETBMOD() and FN_SETBMOD().
  164.  *
  165.  *    When you want to send a message to another user, you
  166.  *    can use the Send Broadcast Message API, FN_SBM().
  167.  *
  168.  *    When you want to send a message to the file server's console, 
  169.  *    you can use the Broadcast to Console API, FN_BTOC().
  170.  *
  171.  *    For your convenience, we have defined two commands in netto.CH
  172.  *    that emulate the CASTON, CASTOFF, and CASTOFF ALL commands found
  173.  *    in NetWare 2.x and 3.x.  These commands simply set the
  174.  *    appropriate broadcast modes.
  175.  *
  176.  *    Emulating NetWare's SEND command
  177.  *    --------------------------------
  178.  *
  179.  *    You'll note that none of these APIs allow you to send to a 
  180.  *    specific USER or GROUP, just a logged in connection ID.
  181.  *    While we work on a fancy set of #commands for this, you can 
  182.  *    do it yourself.
  183.  *
  184.  *    The basic trick is to build up a list of connection numbers.
  185.  *    You get these with the FN_OBJCNUM() function.  If you want 
  186.  *    to send to user BILLY, you can first find out all the 
  187.  *    connections where BILLY is logged in as follows:
  188.  *
  189.  *            aList := fn_objcnum( "BILLY" )
  190.  *            
  191.  *    If !empty( aList ), you can deliver aList directly to FN_SBM().
  192.  *
  193.  *    Finding the connected members of a group is just as simple.
  194.  *    If you want to send to everyone in the "SALES" group, you call:
  195.  *
  196.  *           #include "netto.ch"
  197.  *           aList := fn_objcnum( "SALES", OT_USER_GROUP )
  198.  *
  199.  *    Once you've buit up an array of connection IDs, you can then
  200.  *    call FN_SBM() with the message text and this array.  That's
  201.  *    pretty much all there is to it.
  202.  *
  203.  *    You can simplify even further with something like:
  204.  *
  205.  *       function fn_sndUser( cUser, cMsg )
  206.  *          return fn_sbm( fn_objcnum( cUser ), cMsg )
  207.  *   
  208.  *    How do you send to someone on another file server?
  209.  *    --------------------------------------------------
  210.  *
  211.  *    A variation on the same theme, but a little trickier (which is 
  212.  *    why we hope to implement these in a cleaner #command format
  213.  *    someday).  First, to send to another server, you of course have
  214.  *    to be attached to that server.
  215.  *
  216.  *    Second, you must get the current preferred connection ID and 
  217.  *    save it.   Then, you must set the preferred connection ID, via
  218.  *    the fn_spfcid() function, to the ID of the server you're sending
  219.  *    to.  Next, you send the broadcast message.  Last, you restore
  220.  *    the old preferred connection ID.
  221.  *
  222.  *    Let's see that in action:
  223.  *
  224.  *         function fn_sndUser( cUser, cMsg, cServer )
  225.  *            local aRes, nOldID, nNewID
  226.  *            if !( cServer == nil )
  227.  *               nOldID := fn_pfConid()
  228.  *               nNewID := ascan( fn_fsname(), upper( cServer ) )
  229.  *               if nNewID # 0
  230.  *                  fn_spfcid( nNewID )
  231.  *               endif
  232.  *            endif
  233.  *            aRes := fn_sbm( fn_objcnum( cUser ), cMsg )
  234.  *            if !( cServer == nil )
  235.  *               fn_spfcid( nOldID )
  236.  *            endif
  237.  *            return aRes
  238.  *
  239.  *    We've added the ability to optionally specify a server.  We've
  240.  *    also added a lot more code.  But look it over.
  241.  *
  242.  *    Using the FN_PFEVAL() function, we can simplify the whole
  243.  *    routine down to this:
  244.  *
  245.  *         function fn_sndUser( cUser, cMsg, cServer )
  246.  *            return fn_pfEval( cServer, ;
  247.  *                     { || fn_sbm( fn_objcnum( cUser ), cMsg ) }
  248.  *
  249.  *    [ BETA WARNING! ALL CODE NOT TESTED YET, PLEASE DO SO. ]
  250.  *
  251.  *    You can see that it'll take extra work to parse complex 
  252.  *    server/username, server/groupname pairs on a single command
  253.  *    line.  If you solve the problem before we do, please submit
  254.  *    it, but try to use the same grammar as the NetWare SEND 
  255.  *    command: consult the manual!
  256.  *   
  257.  *    Advanced Stuff
  258.  *    --------------
  259.  *
  260.  *    Depending on how you set the broadcast mode, you can exercise
  261.  *    control over how and when the messages are displayed.  If you
  262.  *    set the broadcast mode to 2 or 3, then the server will queue up
  263.  *    to one message for your workstation but your shell will not display
  264.  *    it.  You can use the Get Broadcast Message API, FN_GBM() to 
  265.  *    retrieve this message and display it yourself.  Of course, you'll
  266.  *    have to poll fairly regularly for this message because only one
  267.  *    will be stored.  Also, each file server the user is attached to
  268.  *    could be holding a message so you'll have to poll around quite
  269.  *    a bit by saving the connection ID, setting the preferred ID, 
  270.  *    issuing the fn_gbm() call, etc, etc.  
  271.  *
  272.  *    Advanced programmers may be interested to know that in shell
  273.  *    versions after 3.01, the shell will issue an interrupt 2Fh
  274.  *    when a message arrives.  If register AX contains 7A85H, then 
  275.  *    CX has the connection ID of the server holding the message 
  276.  *    for you.  Set CX to 0 indicating that you've handled the message,
  277.  *    and chain to the next process hooking interrupt 2FH.  To get the
  278.  *    message, save the current server's ID, set the preferred 
  279.  *    connection ID to the one indicated by CX, and call the 
  280.  *    Get Broadcast Message API.  If you come up with a clean way
  281.  *    of allowing a Clipper programmer to asynchronously handle these
  282.  *    events with a call to a Clipper function, please contact us!
  283.  *
  284.  *  $EXAMPLES$
  285.  *
  286.  *  $INCLUDE$
  287.  *
  288.  *  $SEEALSO$
  289.  *     FN_PFEVAL() FN_SBM() FN_OBJCNUM() FN_SPFCID() FN_PFCONID()
  290.  *  $END$
  291.  */
  292.  
  293.  
  294.  
  295. /*  $DOC$
  296.  *  $FUNCNAME$
  297.  *     CASTON
  298.  *  $CATEGORY$
  299.  *     Message
  300.  *  $ONELINER$
  301.  *     Enable receipt of broadcast messages
  302.  *  $SYNTAX$
  303.  *
  304.  *     CASTON
  305.  *
  306.  *  $ARGUMENTS$
  307.  *
  308.  *  $RETURNS$
  309.  *
  310.  *  $DESCRIPTION$
  311.  *      
  312.  *    Use this call to simulate NetWare's CASTON.  You must #include
  313.  *    netto.CH in order to use it.
  314.  *     
  315.  *  $EXAMPLES$
  316.  *
  317.  *         // don't want to be interrupted
  318.  *         castoff all
  319.  *         longProcess()
  320.  *         caston
  321.  *
  322.  *  $INCLUDE$
  323.  *     netto.CH
  324.  *  $SEEALSO$
  325.  *     CASTOFF
  326.  *  $END$
  327.  */
  328.  
  329.  
  330. /*  $DOC$
  331.  *  $FUNCNAME$
  332.  *     CASTOFF
  333.  *  $CATEGORY$
  334.  *     Message
  335.  *  $ONELINER$
  336.  *     Disable receipt of broadcast messages
  337.  *  $SYNTAX$
  338.  *
  339.  *     CASTOFF [ALL]
  340.  *
  341.  *  $ARGUMENTS$
  342.  *
  343.  *  $RETURNS$
  344.  *
  345.  *  $DESCRIPTION$
  346.  *      
  347.  *    Use this call to simulate NetWare's CASTOFF.  You must #include
  348.  *    netto.CH in order to use it.
  349.  *
  350.  *    CASTOFF by itself will disable receipt of messages from other
  351.  *    workstations.  CASTOFF ALL disables both workstation messages
  352.  *    and messages from the file server console.
  353.  *
  354.  *  $EXAMPLES$
  355.  *
  356.  *         // don't want to be interrupted
  357.  *         castoff all
  358.  *         longProcess()
  359.  *         caston
  360.  *
  361.  *  $INCLUDE$
  362.  *     netto.CH
  363.  *  $SEEALSO$
  364.  *     CASTON
  365.  *  $END$
  366.  */
  367.  
  368.