home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / ckoco4.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  47KB  |  1,378 lines

  1. /* C K O C O 4 . C */
  2.  
  3. /*
  4.   Author: Frank da Cruz  (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  5.             Columbia University Academic Information Systems, New York City.
  6.           Jeffrey E Altman (jaltman@secure-endpoints.com)
  7.             Secure Endpoints Inc., New York City
  8.  
  9.   Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New
  10.   York.
  11. */
  12.  
  13. #include "ckcdeb.h"
  14.  
  15. #ifdef NT
  16. #include <windows.h>
  17. #define strnicmp _strnicmp
  18. #else /* NT */
  19.  
  20. #define INCL_WIN
  21. #define INCL_VIO
  22. #define INCL_ERRORS
  23. #define INCL_DOSPROCESS
  24. #define INCL_DOSSEMAPHORES
  25. #define INCL_DOSDEVIOCTL
  26. #define INCL_WINCLIPBOARD
  27. #define INCL_DOSDATETIME
  28. #define INCL_DOSMEMMGR
  29. #include <os2.h>
  30. #undef COMMENT                /* COMMENT is defined in os2.h */
  31. #endif /* NT */
  32.  
  33. #include "ckcasc.h"
  34. #include "ckcker.h"
  35. #include "ckuusr.h"
  36. #include "ckocon.h"
  37. #include "ckokey.h"
  38. #include "ckcxla.h"             /* Character set translation */
  39. #include "ckcuni.h"             /* Unicode Character Set Translations */
  40. #include <stdio.h>
  41.  
  42. extern int tnlm, tn_nlm;        /* Terminal newline mode, ditto for TELNET */
  43. #ifndef NOTERM
  44. extern int tt_status[VNUM] ;
  45. #endif /* NOTERM */
  46. #ifndef NOLOCAL
  47. extern videobuffer vscrn[] ;
  48. extern enum markmodes markmodeflag[] ;
  49. extern bool xprintff, printon ;
  50. #ifndef NT
  51. extern HAB hab ;
  52. #endif /* NT */
  53.  
  54. static char * selection = NULL ;
  55. static unsigned short * Uselection = NULL;
  56. static int    nselect   = 0 ;
  57. static char * url       = NULL ;
  58. static int    nurl      = 0 ;
  59. static int    url_type  = 0 ;
  60.  
  61. #define MAXURLLEN 4095
  62.  
  63. const char *
  64. GetSelection()
  65. {
  66.     return selection;
  67. }
  68.  
  69. int
  70. GetURLType(void)
  71. {
  72.     return url_type;
  73. }
  74.  
  75. const char *
  76. GetURL()
  77. {
  78.     return url;
  79. }
  80.  
  81. static char *
  82. FindURL( const char * s )
  83. {
  84.     /* We have a string.  Is it a URL? */
  85.     /*  telnet      */
  86.     /*  http(s)     */
  87.     /*  gopher      */
  88.     /*  (s)news     */
  89.     /*  mailto      */
  90.     /*  ftp         */
  91.     /*  tcp, udp, ... */
  92.     /*          Does it have a valid host?  If not, return               */
  93.     /*          Is it telnet: rlogin: ssh:? If so, start a new K95 session */
  94.     /*          Otherwise, start the browser                             */
  95.     /* If not, */
  96.     /*          Check the string to see if it is a mail message          */
  97.     /*               if so, does it have a mailto: prefix? Start Browser */
  98.     /*                          If not, add one and start browser        */
  99.     /*          Otherwise, is it a valid host?  If so, http://<host>/    */
  100.     /*          Does adding 'www' or '.edu', '.com', make it valid?      */
  101.     /*          If so, start browser                                     */
  102.  
  103.     int i, len;
  104.     char * newurl = NULL;
  105.     int mailto = 0;
  106.  
  107.     if ( strnicmp(s,"telnet:",7) &&
  108.          strnicmp(s,"login:",6)  &&
  109.          strnicmp(s,"ssh:",4)  &&
  110.          strnicmp(s,"http:",5) &&
  111.          strnicmp(s,"gopher:",7) &&
  112.          strnicmp(s,"news:",5) &&
  113.          strnicmp(s,"snews:",6) &&
  114.          strnicmp(s,"ftp:",4) &&
  115.          strnicmp(s,"mailto:",7) &&
  116.          strnicmp(s,"https:",6) &&
  117.          strnicmp(s,"ftps:",5) &&
  118.          strnicmp(s,"telnets:",8) &&
  119.          strnicmp(s,"iksd:",5) &&
  120.          strnicmp(s,"kermit:",7) &&
  121.          strnicmp(s,"tcp:", 4) &&
  122.          strnicmp(s,"udp:", 4) )
  123.     {
  124.         /* Not one of the well known URL services */
  125.  
  126.         /* we are not going to perform host checking */
  127.         /* if it looks like a mail address (contains an @) we will preface */
  128.         /* mailto: */
  129.         len = strlen(s);
  130.         for ( i=0;i<len;i++ )
  131.         {
  132.             if ( !mailto && s[i] == '@' ) {
  133.                 mailto = 1;
  134.             }
  135.             else if ( mailto ) {
  136.                 switch ( s[i] ) {
  137.                 case '@':
  138.                 case ',':
  139.                 case '/':
  140.                 case '\\':
  141.                 case '$':
  142.                 case '?':
  143.                 case '|':
  144.                 case '!':
  145.                     mailto = 0 ;
  146.                     break;      /* switch */
  147.                 }
  148.                 if ( !mailto )
  149.                     break;      /* for */
  150.             }
  151.         }
  152.     }
  153.  
  154.     if ( mailto ) {
  155.         newurl = (char *) malloc(strlen(s) + strlen("mailto:") + 1);
  156.         if ( !newurl )
  157.             return(NULL);
  158.  
  159.         strcpy( newurl, "mailto:" );
  160.         strcat( newurl, s);
  161.     } else {
  162.         newurl = (char *) malloc(strlen(s) + 1);
  163.         if ( !newurl )
  164.             return(NULL);
  165.         strcpy( newurl, s );
  166.     }
  167.     len = strlen(newurl);
  168.     if ( newurl[len-1] == '.' || newurl[len-1] == ',' || newurl[len-1] == ';' )
  169.         /* remove unnecessary punctuation */
  170.         newurl[len-1] = '\0';
  171.     return(newurl);
  172. }
  173.  
  174.  
  175. APIRET
  176. VscrnURL( BYTE mode, USHORT row, USHORT col )
  177. {
  178. #ifdef BROWSER
  179.     videoline * line=NULL;
  180.     viocell * cells = NULL;
  181.     char    ch, * str=NULL;
  182.     int i,j,len;
  183.     int brow, bcol, erow, ecol;
  184.     extern bool scrollflag[] ;
  185.     extern char browsurl[];
  186.  
  187.     if ( url )
  188.     {
  189.         free( url ) ;
  190.         url = NULL ;
  191.         nurl = 0 ;
  192.         url_type = 0;
  193.     }
  194.  
  195.     /* First check the hyperlink attribute */
  196.     if ( scrollflag[mode] )
  197.         line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + row );
  198.     else
  199.         line = VscrnGetLineFromTop( mode, row );
  200.     if ( line->vt_char_attrs[col] & VT_CHAR_ATTR_HYPERLINK ) {
  201.         hyperlink * link = hyperlink_get(line->hyperlinks[col]);
  202.         if ( link ) {
  203.             url = strdup(link->str);
  204.             if ( url ) {
  205.                 nurl = strlen( url );
  206.                 url_type = link->type;
  207.                 ckstrncpy( browsurl, url, 4096 );
  208.                 return 0;               /* a valid URL/UNC was found */
  209.             }
  210.         }
  211.         return -1;
  212.     }
  213.  
  214.     /* From the current row,col we need to determine which line contains
  215.        the beginning and end of the string we think might contain a URL.
  216.  
  217.        Compute the length of the string
  218.  
  219.        Then copy the whole string into a temporary buffer
  220.  
  221.      */
  222.  
  223.     /* Find the beginning of the URL */
  224.  
  225.     brow = row;
  226.     bcol = col;
  227.     while(1) {
  228.         if ( scrollflag[mode] )
  229.             line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + brow );
  230.         else
  231.             line = VscrnGetLineFromTop( mode, brow );
  232.         cells = line->cells;
  233.  
  234.         while ( bcol >= 0 ) {
  235.             ch = (CHAR) cells[bcol].c;
  236.             if (ch && (isalnum(ch) || ch == '/' || ch == ':' || ch == '.' || ch == '#' ||
  237.                   ch == '|' || ch == '@' || ch == '!' || ch == '-' || ch == '_' ||
  238.                   ch == '?' || ch == '%' || ch == '&' || ch == '+' || ch == '\\' ||
  239.                   ch == '=' || ch == ';' || ch == '~' || ch == ',' || ch == '$'))
  240.             {
  241.                 bcol--;
  242.             } else {
  243.                 bcol++;
  244.                 if ( bcol >= line->width ) {
  245.                     bcol = 0;
  246.                     brow++;
  247.                 }
  248.                 goto bfound;
  249.             }
  250.         }
  251.  
  252.         bcol = line->width-1;
  253.         brow--;
  254.     }
  255.   bfound:
  256.  
  257.     /* Find the end of the URL */
  258.     erow = row;
  259.     ecol = col;
  260.     while(1) {
  261.         if ( scrollflag[mode] )
  262.             line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + erow );
  263.         else
  264.             line = VscrnGetLineFromTop( mode, erow );
  265.         cells = line->cells;
  266.  
  267.         while ( ecol < line->width ) {
  268.             ch = (CHAR) cells[ecol].c;
  269.             if (ch && (isalnum(ch) || ch == '/' || ch == ':' || ch == '.' || ch == '#' ||
  270.                   ch == '|' || ch == '@' || ch == '!' || ch == '-' || ch == '_' ||
  271.                   ch == '?' || ch == '%' || ch == '&' || ch == '+' || ch == '\\' ||
  272.                   ch == '=' || ch == ';' || ch == '~' || ch == ',' || ch == '$'))
  273.             {
  274.                 ecol++;
  275.             } else {
  276.                 ecol--;
  277.                 if ( ecol < 0 ) {
  278.                     ecol = line->width - 1;
  279.                     erow--;
  280.                 }
  281.                 goto efound;
  282.             }
  283.         }
  284.  
  285.         ecol = 0;
  286.         erow++;
  287.     }
  288.   efound:
  289.  
  290.     str = (char *) malloc((erow - brow + 1) * line->width);
  291.     if ( !str )
  292.         return(-1);
  293.  
  294.     if ( brow == erow ) {
  295.         if ( scrollflag[mode] )
  296.             line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + brow );
  297.         else
  298.             line = VscrnGetLineFromTop( mode, brow );
  299.         cells = line->cells;
  300.  
  301.         for ( i=bcol,len=0;i<=ecol;i++,len++ )
  302.             str[len] = (CHAR) cells[i].c;
  303.         str[len] = '\0';
  304.     } else {
  305.         /* handle the first row - bcol to end */
  306.         if ( scrollflag[mode] )
  307.             line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + brow );
  308.         else
  309.             line = VscrnGetLineFromTop( mode, brow );
  310.         cells = line->cells;
  311.  
  312.         for ( i=bcol,len=0;i<line->width;i++,len++ )
  313.             str[len] = (CHAR) cells[i].c;
  314.  
  315.         /* handle the complete rows if there are any */
  316.         for ( j=brow+1; j<erow; j++ ) {
  317.             if ( scrollflag[mode] )
  318.                 line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + j );
  319.             else
  320.                 line = VscrnGetLineFromTop( mode, j );
  321.             cells = line->cells;
  322.  
  323.             for ( i=0;i<line->width;i++,len++ )
  324.                 str[len] = (CHAR) cells[i].c;
  325.         }
  326.  
  327.         /* handle the last row - begin to ecol */
  328.         if ( scrollflag[mode] )
  329.             line = VscrnGetLine( mode, VscrnGetScrollTop(mode) + erow );
  330.         else
  331.             line = VscrnGetLineFromTop( mode, erow );
  332.         cells = line->cells;
  333.  
  334.         for ( i=0;i<=ecol;i++,len++ )
  335.             str[len] = (CHAR) cells[i].c;
  336.         str[len] = '\0';
  337.     }
  338.  
  339.     debug(F000,"mouseurl detected",str,0);
  340.     if (len == 0) {
  341.         free(str);
  342.         return -1;
  343.     }
  344.  
  345.     url = FindURL(str);
  346.     free(str);
  347.     if ( url ) {
  348.         nurl = strlen( url );
  349.         url_type = HYPERLINK_URL;
  350.         ckstrncpy( browsurl, url, 4096 );
  351.         return 0;               /* a valid URL was found */
  352.     }
  353. #endif /* BROWSER */
  354.     return -1;                  /* failure to find a valid URL */
  355. }
  356.  
  357. /* 
  358.  * mode = 0 - word wrap with EOL
  359.  * mode = 1 - word wrap without EOL
  360.  * mode = 2 - box with EOL (not yet implemented)
  361.  */
  362.  
  363. APIRET
  364. VscrnSelect( BYTE vmode, int mode )
  365. {
  366.     /* This code does not work for Hebrew and other BiDi languages */
  367.     videoline * line = NULL;
  368.     ULONG y = 0;
  369.     USHORT x = 0;
  370.     BYTE   *p = NULL;
  371.     USHORT *pU = NULL;
  372.     APIRET rc = 0 ;
  373.  
  374.     if ( selection )
  375.     {
  376.         free( selection ) ;
  377.         selection = NULL ;
  378.         nselect = 0 ;
  379.     }
  380.     if ( Uselection ) {
  381.         free( Uselection ) ;
  382.         Uselection = NULL ;
  383.     }
  384.  
  385.     if (vscrn[vmode].marktop == -1 || vscrn[vmode].markbot == -1 ) {
  386.         bleep(BP_WARN) ;
  387.         return -1 ;
  388.         }
  389.  
  390.     /* Determine size of Selected Text */
  391.  
  392.     y = vscrn[vmode].marktop ;
  393.     while (1) {
  394.         line = &vscrn[vmode].lines[y] ;
  395.         if ( line->markbeg != -1 && line->markshowend != -1 ) {
  396.             for ( x  = line->markbeg ; x <= line->markshowend ; x++ )
  397.                 nselect++ ;
  398. #ifndef NT
  399.             /* there is an OS/2 compiler bug here */
  400.             /* when optimized it generates an infinite loop */
  401.             debug(F100,"VscrnSelect() infinite loop?","",0);
  402. #endif /* NT */
  403.         }
  404.  
  405.         if ( y == vscrn[vmode].markbot ) {
  406.             break;
  407.         }
  408.         else {
  409.             if ( mode == 0 ) {
  410.                 /* Add line termination */
  411.                 nselect++ ; /* '\r' */
  412.                 nselect++ ; /* '\n' */
  413.             }
  414.             /* Advance counter */
  415.             y++ ;
  416.             if ( y == vscrn[vmode].linecount )
  417.                 y = 0 ;
  418.         }
  419.     }
  420.         nselect++ ;  /* terminating NUL */
  421.  
  422.     selection = (char *) malloc( nselect ) ;
  423.     if ( !selection )
  424.     {
  425.         nselect = 0 ;
  426.         return -1;
  427.     }
  428.     Uselection = (unsigned short *) malloc( nselect * 2 ) ;
  429.     if ( !Uselection )
  430.     {
  431.         free(selection);
  432.         selection = NULL;
  433.         nselect = 0 ;
  434.         return -1;
  435.     }
  436.  
  437.     /* Copy the data to the selection buffer */
  438.     p = selection ;
  439.     pU = Uselection ;
  440.  
  441.     while (1) {
  442.         line = &vscrn[vmode].lines[vscrn[vmode].marktop] ;
  443.         if ( line->markbeg != -1 && line->markshowend != -1 )
  444.             for ( line->markbeg ;
  445.                 line->markbeg <= line->markshowend;
  446.                 line->markbeg++ ) {
  447. #ifdef NT
  448.                 if ( isunicode() ) {
  449.                     extern int tcsl;
  450.                     *p = xl_tx[tcsl](line->cells[line->markbeg].c);
  451.                     *pU = line->cells[line->markbeg].c;
  452.                 } else
  453. #endif /* NT */
  454.                 {
  455.                     *pU = *p = line->cells[line->markbeg].c;
  456.                 }
  457.                 p++ ;
  458.                 pU++;
  459.             }
  460.         line->markbeg = line->markshowend = line->markend = -1 ;
  461.  
  462.         if ( vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  463.             vscrn[vmode].marktop = vscrn[vmode].markbot = -1 ;
  464.             break;
  465.         }
  466.         else {
  467.             if ( mode == 0 ) {
  468.                 /* Add line termination */
  469.                 *pU++ = *p++ = '\r' ;
  470.                 *pU++ = *p++ = '\n' ;
  471.             }
  472.  
  473.             /* Advance counter */
  474.             vscrn[vmode].marktop++ ;
  475.             if ( vscrn[vmode].marktop == vscrn[vmode].linecount )
  476.                 vscrn[vmode].marktop = 0 ;
  477.         }
  478.     }
  479.     *pU = *p = '\0' ;  /* Terminating NUL */
  480.     return rc;
  481. }
  482.  
  483. /* This code does not work for Hebrew and other BiDi languages */
  484. APIRET
  485. CopyVscrnToKbdBuffer( BYTE vmode, int select_mode ) {
  486.     APIRET rc = 0 ;
  487.     BYTE * pData = NULL ;
  488.     int i = 0, j = 0, len = 0 ;
  489.  
  490.     if ( VscrnSelect(vmode,select_mode) )
  491.         return -1 ;
  492.  
  493.     len = nselect - 1;          /* nselect includes terminating NUL */
  494.     if ( len == 0 )
  495.         return(0);
  496.  
  497.     if ( isunicode() ) {
  498.         /* Vscrn is in Unicode.  We must perform translations to both */
  499.         /* lcs for keyboard and rcs for sending.  Do not allow        */
  500.         /* sendcharsduplex() to translate.                            */
  501.  
  502.         if ( vmode == VTERM ) {
  503.             unsigned char * bytes;
  504.             int nbytes;
  505.  
  506.             nbytes = utorxlat(Uselection[0], &bytes);
  507.             while ( nbytes-- > 0 )
  508.                 sendcharduplex(*bytes++,TRUE);
  509.             for ( i=1; i<len; i++ ) {
  510.                 if ( Uselection[i-1] != CR || Uselection[i] != LF ) {
  511.                     nbytes = utorxlat(Uselection[i], &bytes);
  512.                     while ( nbytes-- > 0 )
  513.                         sendcharduplex(*bytes++,TRUE);
  514.                 }
  515.             }
  516.         } else {
  517.             pData = (char *)malloc(len+1);
  518.             if ( pData == NULL )
  519.                 return -1;
  520.  
  521.             pData[0] = utolxlat(Uselection[0]);
  522.             for ( i=1, j=1 ; i<len ; i++ )
  523.                 if ( Uselection[i-1] != CR || Uselection[i] != LF )
  524.                     pData[j++] = utolxlat(selection[i]);
  525.             pData[j] = '\0';
  526.             putkeystr( vmode, pData );
  527.         }
  528.     } else {
  529.         /* The Vscrn is in the local character set                */
  530.         /* Allow translation to be performed by sendcharsduplex() */
  531.  
  532.         pData = (char *)malloc(len+1);
  533.         if ( pData == NULL )
  534.             return -1;
  535.  
  536.         pData[0] = selection[0];
  537.         for ( i=1, j=1 ; i<len ; i++ )
  538.             if ( selection[i-1] != CR || selection[i] != LF )
  539.                 pData[j++] = selection[i] ;
  540.         pData[j] = '\0';
  541.  
  542.         if ( vmode == VTERM )
  543.             sendcharsduplex(pData,j,FALSE);
  544.         else
  545.             putkeystr( vmode, pData );
  546.  
  547.         free(pData);
  548.     }
  549.     return rc ;
  550. }
  551.  
  552. APIRET
  553. CopyClipboardToKbdBuffer( BYTE vmode )
  554. {
  555.     int i = 0 ;
  556.     APIRET rc = -1 ;
  557.     BYTE * hClipbrdData ;
  558.     USHORT * pUClipbrdData = 0;
  559.     BYTE * pClipbrdData = 0 ;
  560.     BYTE * pClipboard ;
  561.     int use_unicode = (isunicode() && !isWin95());
  562.  
  563. #ifdef NT
  564.     HGLOBAL hClipboard = NULL ;
  565.  
  566.     if ( OpenClipboard( NULL ) )
  567.     {
  568.         if ( use_unicode ) {
  569.             if ( hClipboard = (BYTE *) GetClipboardData( CF_UNICODETEXT ) )
  570.             {
  571.                 hClipbrdData = GlobalLock(hClipboard) ;
  572.                 pUClipbrdData = wcsdup( (const wchar_t *) hClipbrdData ) ;
  573.                 GlobalUnlock( hClipboard ) ;
  574.             }
  575.         } else {
  576.             if ( hClipboard = (BYTE *) GetClipboardData( CF_TEXT ) )
  577.             {
  578.                 hClipbrdData = GlobalLock(hClipboard) ;
  579.                 pClipbrdData = strdup( hClipbrdData ) ;
  580.                 GlobalUnlock( hClipboard ) ;
  581.             }
  582.         }
  583.         CloseClipboard() ;
  584.     }
  585.     if ( pClipbrdData && !use_unicode )
  586.         CharToOem( pClipbrdData, pClipbrdData );
  587. #else /* NT */
  588.     pClipbrdData = GetTextFromClipboardServer() ;
  589.  
  590.     if ( !pClipbrdData ) {
  591.         if ( rc = WinOpenClipbrd(hab) ) {
  592.             hClipbrdData = (BYTE *) WinQueryClipbrdData( hab, CF_TEXT ) ;
  593.             if ( !DosGetSharedMem( hClipbrdData, PAG_READ ) )
  594.             {
  595.                 pClipbrdData = strdup( hClipbrdData ) ;
  596.  
  597.                 /* We must copy the text back to the Clipboard because the   */
  598.                 /* GetSharedMemory call screwed up the clipboard.  We're not */
  599.                 /* supposed to do things like that.                          */
  600.                 if ( !DosAllocSharedMem( (PPVOID) &pClipboard, 0, strlen(pClipbrdData)+1,
  601.                                          PAG_COMMIT | PAG_READ | PAG_WRITE |
  602.                                          OBJ_GIVEABLE | OBJ_GETTABLE ) )
  603.                 {
  604.                     strcpy( pClipboard, pClipbrdData ) ;
  605.                     WinSetClipbrdData( hab, (ULONG) pClipboard, CF_TEXT, CFI_POINTER ) ;
  606.                     DosFreeMem( pClipboard ) ;
  607.                 }
  608.             }
  609.             WinCloseClipbrd( hab ) ;
  610.         }
  611.     }
  612. #endif /* NT */
  613.  
  614.     if ( use_unicode ) {
  615.         if ( pUClipbrdData ) {
  616.             int i=0, j=0, len = 0;
  617.  
  618.             len = wcslen(pUClipbrdData);
  619.             debug(F111,"Clipboard","pUClipbrdData length",len);
  620.  
  621.             if ( vmode == VTERM ) {
  622.                 unsigned char * bytes, * buf;
  623.                 int nbytes, bytecount=0;
  624.  
  625.                 nbytes = utorxlat(pUClipbrdData[0], &bytes);
  626.                 if ( nbytes > 0 )
  627.                     bytecount = nbytes;
  628.                 for ( i=1; i<len; i++ ) {
  629.                     if ( pUClipbrdData[i-1] != CR || pUClipbrdData[i] != LF ) {
  630.                         nbytes = utorxlat(pUClipbrdData[i], &bytes);
  631.                         if ( nbytes > 0 )
  632.                             bytecount += nbytes;
  633.                     }
  634.                 }
  635.  
  636.                 buf = (unsigned char *) malloc(bytecount+1);
  637.  
  638.                 nbytes = utorxlat(pUClipbrdData[0], &bytes);
  639.                 while ( nbytes-- > 0 )
  640.                     buf[j++] = *bytes++;
  641.                 for ( i=1; i<len; i++ ) {
  642.                     if ( pUClipbrdData[i-1] != CR || pUClipbrdData[i] != LF ) {
  643.                         nbytes = utorxlat(pUClipbrdData[i], &bytes);
  644.                         while ( nbytes-- > 0 )
  645.                             buf[j++] = *bytes++;
  646.                     }
  647.                 }
  648.                 sendcharsduplex(buf,bytecount,TRUE);
  649.                 free(buf);
  650.                 rc = 0;
  651.             } else {
  652.                 char * pData = NULL;
  653.                 pData = (char *)malloc(len+2);
  654.                 debug(F111,"Clipboard","pData",pData);
  655.                 if ( pData != NULL ) {
  656.                     pData[0] = utolxlat(pUClipbrdData[0]);
  657.                     for ( i=1, j=1 ; i<len ; i++ )
  658.                         if ( pUClipbrdData[i-1] != CR || pUClipbrdData[i] != LF )
  659.                             pData[j++] = utolxlat(pUClipbrdData[i]);
  660.                     pData[j] = '\0';
  661.                     debug(F111,"Clipboard","pData length",j);
  662.                     putkeystr( vmode, pData );
  663.                     free(pData);
  664.                     rc = 0 ;
  665.                 }
  666.                 else {
  667.                     rc = -1;
  668.                 }
  669.             }
  670.             free( pUClipbrdData ) ;
  671.         }
  672.     } else {
  673.         if ( pClipbrdData ) {
  674.             char * pData = NULL;
  675.             int i=0, j=0, len = 0;
  676.  
  677.             len = strlen(pClipbrdData);
  678.             debug(F111,"Clipboard","pClipbrdData length",len);
  679.             pData = (char *)malloc(len+2);
  680.             debug(F111,"Clipboard","pData",pData);
  681.             if ( pData != NULL ) {
  682.                 pData[0] = pClipbrdData[0];
  683.                 for ( i=1, j=1 ; i<len ; i++ )
  684.                     if ( pClipbrdData[i-1] != CR || pClipbrdData[i] != LF )
  685.                         pData[j++] = pClipbrdData[i] ;
  686.                 pData[j] = '\0';
  687.                 debug(F111,"Clipboard","pData length",j);
  688.  
  689.                 if ( vmode == VTERM )
  690.                     sendcharsduplex(pData,j,FALSE);
  691.                 else
  692.                     putkeystr( vmode, pData );
  693.                 free(pData);
  694.                 rc = 0 ;
  695.             }
  696.             else {
  697.                 rc = -1;
  698.             }
  699.             free( pClipbrdData ) ;
  700.         }
  701.     }
  702.  
  703.     if ( rc )
  704.         bleep( BP_FAIL ) ;
  705.     return rc ;
  706. }
  707.  
  708. APIRET
  709. CopyVscrnToClipboard( BYTE vmode, int select_mode )
  710. {
  711.     ULONG  ClipBoardSz = 0 ;
  712.     BYTE * pClipboard = 0 ;
  713. #ifdef NT
  714.     HGLOBAL hClipboard = NULL ;
  715. #endif /* NT */
  716.     APIRET rc = 0 ;
  717.     int use_unicode = (isunicode() && !isWin95());
  718.  
  719.     if ( VscrnSelect(vmode, select_mode) )
  720.         return -1 ;
  721.  
  722.     /* Determine size of Clipboard */
  723.     ClipBoardSz = use_unicode ? 2 * nselect : nselect ;
  724.  
  725.     /* Allocate Clipboard Buffer */
  726. #ifdef NT
  727.     if ( (hClipboard = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, ClipBoardSz )) == NULL )
  728. #else /* NT */
  729.     if ( rc = DosAllocSharedMem( (PPVOID) &pClipboard, 0, ClipBoardSz,
  730.                    PAG_COMMIT | PAG_READ | PAG_WRITE |
  731.                    OBJ_GIVEABLE | OBJ_GETTABLE ) )
  732. #endif /* NT */
  733.     {
  734.         bleep( BP_FAIL ) ;
  735.         return -1 ;
  736.     }
  737. #ifdef NT
  738.     else
  739.     {
  740.         if ( ( pClipboard = GlobalLock( hClipboard )) == NULL )
  741.         {
  742.             GlobalFree( hClipboard ) ;
  743.             bleep( BP_FAIL ) ;
  744.             return -1 ;
  745.         }
  746.         memset( pClipboard, 0, GlobalSize( hClipboard ) ) ;
  747.     }
  748. #endif /* NT */
  749.  
  750.     /* Copy the data to the clibboard buffer */
  751.     if ( use_unicode )
  752.         memcpy( pClipboard, Uselection, ClipBoardSz );
  753.     else
  754.         strcpy( pClipboard, selection ) ;
  755.  
  756. #ifdef NT
  757.     if ( !use_unicode )
  758.         OemToChar( pClipboard, pClipboard );
  759.     GlobalUnlock( hClipboard ) ;
  760.     if ( OpenClipboard(NULL) )
  761.     {
  762.        EmptyClipboard() ;
  763.        if ( !SetClipboardData( use_unicode ? CF_UNICODETEXT : CF_TEXT, hClipboard ) )
  764.        {
  765.           GlobalFree( hClipboard ) ;
  766.           debug(F101,"PutClipboardData failed","",GetLastError() ) ;
  767.        }
  768.        CloseClipboard() ;
  769.     }
  770. #else /* NT */
  771.     if ( PutTextToClipboardServer( pClipboard ) ) {
  772.         DosFreeMem( pClipboard ) ;
  773.         }
  774.     else if ( WinOpenClipbrd( hab ) ) {
  775.        WinEmptyClipbrd( hab ) ;
  776.        if ( !WinSetClipbrdData( hab, (ULONG) pClipboard, CF_TEXT, CFI_POINTER ) )
  777.            DosFreeMem( pClipboard ) ;
  778.        WinCloseClipbrd( hab ) ;
  779.        }
  780.    else {
  781.       DosFreeMem( pClipboard ) ;
  782.       rc = -1 ;
  783.       }
  784. #endif /* NT */
  785.     return rc ;
  786. }
  787.  
  788.  
  789. APIRET
  790. CopyVscrnToPrinter(BYTE vmode, int select_mode)
  791. {
  792.     bool printstate = printon ;
  793.     APIRET rc = 0 ;
  794.  
  795.     if ( VscrnSelect(vmode,select_mode) )
  796.         return -1 ;
  797.  
  798.     /* Copy the data to the printer buffer */
  799.  
  800.     if (!printstate)
  801.         printeron() ;
  802.  
  803.     if (!printon)
  804.     bleep( BP_FAIL ) ;
  805.     else {
  806.     prtstr(selection,nselect-1);        /* nselect includes NUL */
  807.     if (xprintff)
  808.         prtchar(FF);
  809.     }
  810.     if (!printstate)
  811.         printeroff();
  812.     return rc ;
  813. }
  814.  
  815.  
  816. void
  817. markstart( BYTE vmode )
  818. {
  819.     if ( markmodeflag[vmode] == marking ) {
  820.         VscrnUnmarkAll(vmode) ;
  821.         }
  822.     markmodeflag[vmode] = marking ;
  823.     VscrnMark( vmode,(VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y)%vscrn[vmode].linecount,
  824.         vscrn[vmode].cursor.x, vscrn[vmode].cursor.x ) ;
  825. }
  826.  
  827. void
  828. markcancel( BYTE vmode )
  829. {
  830.     markmodeflag[vmode] = notmarking ;
  831.     VscrnUnmarkAll(vmode) ;
  832. }
  833.  
  834. void
  835. markdownone( BYTE vmode )
  836. {
  837.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  838.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  839.  
  840.     if ( markmodeflag[vmode] == marking &&
  841.         curline != VscrnGetEnd(vmode)) {
  842.         if ( vscrn[vmode].marktop == curline &&
  843.             vscrn[vmode].lines[vscrn[vmode].marktop].markbeg == vscrn[vmode].cursor.x ) {
  844.             if ( vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  845.                 if ( vscrn[vmode].lines[vscrn[vmode].marktop].markbeg !=
  846.                      vscrn[vmode].lines[vscrn[vmode].marktop].markend )
  847.                    VscrnUnmark( vmode, vscrn[vmode].marktop,
  848.                                  vscrn[vmode].lines[vscrn[vmode].marktop].markbeg,
  849.                                  vscrn[vmode].lines[vscrn[vmode].marktop].markend-1 ) ;
  850.                VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].lines[vscrn[vmode].markbot].markend,
  851.                            vscrn[vmode].lines[vscrn[vmode].markbot].width ) ;
  852.                VscrnMark( vmode, (vscrn[vmode].markbot+1)%vscrn[vmode].linecount, 0,
  853.                            vscrn[vmode].cursor.x ) ;
  854.             }
  855.             else {
  856.                 VscrnUnmark( vmode, vscrn[vmode].marktop, vscrn[vmode].cursor.x, MAXTERMCOL ) ;
  857.                 if ( vscrn[vmode].marktop == vscrn[vmode].markbot &&
  858.                     vscrn[vmode].cursor.x >= vscrn[vmode].lines[vscrn[vmode].markbot].markend ) {
  859.                     VscrnUnmark( vmode, vscrn[vmode].marktop, 0,
  860.                         vscrn[vmode].lines[vscrn[vmode].markbot].markend-1 ) ;
  861.                     VscrnMark( vmode, vscrn[vmode].markbot,
  862.                         vscrn[vmode].lines[vscrn[vmode].markbot].markend, vscrn[vmode].cursor.x ) ;
  863.                     }
  864.                 else {
  865.                     if ( vscrn[vmode].cursor.x > 0 )
  866.                         VscrnUnmark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x-1 );
  867.                     }
  868.                 }
  869.             }
  870.         else {
  871.             VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x,
  872.                 vscrn[vmode].lines[vscrn[vmode].markbot].width ) ;
  873.             if ( vscrn[vmode].markbot != vscrn[vmode].end )
  874.                 VscrnMark( vmode, (vscrn[vmode].markbot+1)%vscrn[vmode].linecount, 0,
  875.                     vscrn[vmode].cursor.x ) ;
  876.             }
  877.         }
  878.  
  879.     if ( markmodeflag[vmode] == inmarkmode ||
  880.         markmodeflag[vmode] == marking && curline != VscrnGetEnd(vmode) ) {
  881.         if ( vscrn[vmode].cursor.y == VscrnGetHeight(vmode)-(tt_status[vmode]?2:1) ) {
  882.             if ( VscrnMoveScrollTop(vmode,1) < 0 )
  883.                 bleep(BP_FAIL);
  884.             }
  885.         else
  886.             vscrn[vmode].cursor.y++ ;
  887.         }
  888.     else {
  889.         bleep(BP_FAIL);
  890.         }
  891.  
  892. }
  893.  
  894. void
  895. markupone( BYTE vmode )
  896. {
  897.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  898.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  899.  
  900.     if ( markmodeflag[vmode] == marking &&
  901.         curline != VscrnGetBegin(vmode) ) {
  902.         if ( vscrn[vmode].markbot == curline &&
  903.             vscrn[vmode].lines[vscrn[vmode].markbot].markend == vscrn[vmode].cursor.x ) {
  904.             if ( vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  905.                 if ( vscrn[vmode].lines[vscrn[vmode].markbot].markbeg !=
  906.                     vscrn[vmode].lines[vscrn[vmode].markbot].markend )
  907.                     VscrnUnmark( vmode, vscrn[vmode].markbot,
  908.                         vscrn[vmode].lines[vscrn[vmode].markbot].markbeg+1,
  909.                         vscrn[vmode].lines[vscrn[vmode].markbot].markend ) ;
  910.                 VscrnMark( vmode, vscrn[vmode].marktop, 0,
  911.                     vscrn[vmode].lines[vscrn[vmode].marktop].markbeg ) ;
  912.                 VscrnMark( vmode, (vscrn[vmode].marktop-1+vscrn[vmode].linecount)%vscrn[vmode].linecount,
  913.                     vscrn[vmode].cursor.x,
  914.                     vscrn[vmode].lines[(vscrn[vmode].marktop-1+vscrn[vmode].linecount)
  915.                     %vscrn[vmode].linecount].width ) ;
  916.                 }
  917.             else {
  918.                 VscrnUnmark( vmode, vscrn[vmode].markbot, 0, vscrn[vmode].cursor.x ) ;
  919.                 if ( vscrn[vmode].marktop == vscrn[vmode].markbot &&
  920.                     vscrn[vmode].cursor.x <= vscrn[vmode].lines[vscrn[vmode].marktop].markbeg ) {
  921.                     VscrnUnmark( vmode, vscrn[vmode].marktop,
  922.                         vscrn[vmode].lines[vscrn[vmode].marktop].markbeg+1, MAXTERMCOL ) ;
  923.                     VscrnMark( vmode, vscrn[vmode].marktop, vscrn[vmode].cursor.x,
  924.                         vscrn[vmode].lines[vscrn[vmode].marktop].markbeg ) ;
  925.                     }
  926.                 else {
  927.                     VscrnUnmark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x+1, MAXTERMCOL );
  928.                     }
  929.                 }
  930.             }
  931.         else {
  932.             VscrnMark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x ) ;
  933.             if ( vscrn[vmode].marktop != vscrn[vmode].beg )
  934.                 VscrnMark( vmode, (vscrn[vmode].marktop-1+vscrn[vmode].linecount)%vscrn[vmode].linecount,
  935.                     vscrn[vmode].cursor.x,
  936.                     vscrn[vmode].lines[(vscrn[vmode].marktop-1+vscrn[vmode].linecount)
  937.                     %vscrn[vmode].linecount].width ) ;
  938.             }
  939.  
  940.         }
  941.  
  942.     if ( markmodeflag[vmode] == inmarkmode ||
  943.         markmodeflag[vmode] == marking &&
  944.         curline != VscrnGetBegin(vmode) ) {
  945.         if ( vscrn[vmode].cursor.y == 0 ) {
  946.             if ( VscrnMoveScrollTop(vmode,-1) < 0 )
  947.                 bleep(BP_FAIL);
  948.             }
  949.         else
  950.             vscrn[vmode].cursor.y-- ;
  951.         }
  952.     else {
  953.         bleep(BP_FAIL);
  954.         }
  955. }
  956.  
  957. void
  958. markleftone( BYTE vmode )
  959. {
  960.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  961.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  962.  
  963.     if ( markmodeflag[vmode] == marking && vscrn[vmode].cursor.x > 0 ) {
  964.         if ( vscrn[vmode].marktop == curline &&
  965.             vscrn[vmode].lines[vscrn[vmode].marktop].markbeg == vscrn[vmode].cursor.x ) {
  966.             VscrnMark( vmode, vscrn[vmode].marktop, vscrn[vmode].cursor.x-1, vscrn[vmode].cursor.x-1 ) ;
  967.         }
  968.         else {
  969.             VscrnUnmark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x, vscrn[vmode].cursor.x ) ;
  970.         }
  971.     }
  972.  
  973.     if ( vscrn[vmode].cursor.x == 0 )
  974.         bleep(BP_FAIL);
  975.     else
  976.         vscrn[vmode].cursor.x-- ;
  977. }
  978.  
  979. void
  980. markrightone( BYTE vmode )
  981. {
  982.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  983.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  984.  
  985.     if ( markmodeflag[vmode] == marking && vscrn[vmode].cursor.x < VscrnGetWidth(VTERM)-1 ) {
  986.         if ( vscrn[vmode].markbot == curline &&
  987.             vscrn[vmode].lines[vscrn[vmode].markbot].markend == vscrn[vmode].cursor.x ) {
  988.             VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x+1, vscrn[vmode].cursor.x+1 ) ;
  989.         }
  990.         else {
  991.             VscrnUnmark( vmode, vscrn[vmode].marktop, vscrn[vmode].cursor.x, vscrn[vmode].cursor.x ) ;
  992.         }
  993.     }
  994.  
  995.     if ( vscrn[vmode].cursor.x == VscrnGetWidth(VTERM)-1 )
  996.         bleep(BP_FAIL);
  997.     else
  998.         vscrn[vmode].cursor.x++ ;
  999. }
  1000.  
  1001. void
  1002. markdownscreen( BYTE vmode )
  1003. {
  1004.    int count = (tt_status[vmode]?1:0) ;
  1005.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  1006.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  1007.  
  1008.     if ( markmodeflag[vmode] == marking &&
  1009.         curline != VscrnGetEnd(vmode) ) {
  1010.         if ( vscrn[vmode].marktop == curline &&
  1011.              vscrn[vmode].marktop != vscrn[vmode].markbot &&
  1012.             vscrn[vmode].lines[vscrn[vmode].marktop].markbeg == vscrn[vmode].cursor.x ) {
  1013.             while ( count < VscrnGetHeight(vmode) &&
  1014.                     ( vscrn[vmode].marktop < ( vscrn[vmode].markbot - 1 + vscrn[vmode].linecount)%vscrn[vmode].linecount ) )
  1015.             {
  1016.                count++ ;
  1017.                VscrnUnmark( vmode, vscrn[vmode].marktop, 0, MAXTERMCOL ) ;
  1018.                if ( vscrn[vmode].cursor.x > 0 ) {
  1019.                   VscrnUnmark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x-1 );
  1020.                }
  1021.             }
  1022.         }
  1023.  
  1024.         if ( count < VscrnGetHeight(vmode) && vscrn[vmode].marktop ==
  1025.             (vscrn[vmode].markbot-1+vscrn[vmode].linecount)%vscrn[vmode].linecount ) {
  1026.             count++ ;
  1027.             VscrnUnmark( vmode, vscrn[vmode].marktop, 0, MAXTERMCOL ) ;
  1028.             if ( vscrn[vmode].cursor.x <= vscrn[vmode].lines[vscrn[vmode].marktop].markend ) {
  1029.                 VscrnUnmark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x-1 ) ;
  1030.                 }
  1031.             else { /* vscrn[vmode].cursor.x > vscrn[vmode].lines[vscrn[vmode].marktop].markend */
  1032.                 VscrnUnmark( vmode, vscrn[vmode].marktop, 0,
  1033.                     vscrn[vmode].lines[vscrn[vmode].marktop].markend-1 ) ;
  1034.                 VscrnMark( vmode, vscrn[vmode].marktop, vscrn[vmode].lines[vscrn[vmode].marktop].markend,
  1035.                     vscrn[vmode].cursor.x ) ;
  1036.                 }
  1037.             }
  1038.  
  1039.         if ( count < VscrnGetHeight(vmode) &&
  1040.             vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  1041.             count++ ;
  1042.             if ( vscrn[vmode].cursor.x == vscrn[vmode].lines[vscrn[vmode].markbot].markbeg ) {
  1043.                 VscrnUnmark( vmode, vscrn[vmode].markbot, 0,
  1044.                     vscrn[vmode].lines[vscrn[vmode].markbot].markend-1 ) ;
  1045.                 }
  1046.             VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].lines[vscrn[vmode].markbot].markend,
  1047.                 MAXTERMCOL ) ;
  1048.             if ( vscrn[vmode].markbot != vscrn[vmode].end )
  1049.                 VscrnMark( vmode, (vscrn[vmode].markbot+1)%vscrn[vmode].linecount, 0,
  1050.                     vscrn[vmode].cursor.x ) ;
  1051.             }
  1052.  
  1053.         while ( count < VscrnGetHeight(vmode) &&
  1054.                 vscrn[vmode].markbot != vscrn[vmode].end ) {
  1055.             count++ ;
  1056.             VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x,
  1057.                 vscrn[vmode].lines[vscrn[vmode].markbot].width ) ;
  1058.             if ( vscrn[vmode].markbot != vscrn[vmode].end )
  1059.                 VscrnMark( vmode, (vscrn[vmode].markbot+1)%vscrn[vmode].linecount, 0,
  1060.                 vscrn[vmode].cursor.x ) ;
  1061.             }
  1062.         }
  1063.  
  1064.     if ( VscrnMoveScrollTop(vmode, VscrnGetHeight(vmode)-(tt_status[vmode]?1:0)) < 0 ) {
  1065.         LONG oldscrolltop = VscrnGetScrollTop(vmode);
  1066.         if ( VscrnSetScrollTop(vmode, VscrnGetTop(vmode)) < 0 )
  1067.             bleep(BP_WARN);
  1068.         else if ( oldscrolltop != VscrnGetScrollTop(vmode) )
  1069.             vscrn[vmode].cursor.y +=
  1070.             (VscrnGetHeight(vmode) - (tt_status[vmode]?1:0)
  1071.               - (vscrn[vmode].scrolltop - oldscrolltop)
  1072.               + vscrn[vmode].linecount) % vscrn[vmode].linecount ;
  1073.         else vscrn[vmode].cursor.y = VscrnGetHeight(vmode)
  1074.             -(tt_status[vmode]?1:0)-1 /* zero based */ ;
  1075.         }
  1076. }
  1077.  
  1078. void
  1079. markupscreen( BYTE vmode )
  1080. {
  1081.     int count = 0 ;
  1082.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  1083.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  1084.  
  1085.     if ( markmodeflag[vmode] == marking &&
  1086.         curline != VscrnGetBegin(vmode) ) {
  1087.         if ( vscrn[vmode].markbot == curline &&
  1088.              vscrn[vmode].marktop != vscrn[vmode].markbot &&
  1089.             vscrn[vmode].lines[vscrn[vmode].markbot].markend == vscrn[vmode].cursor.x ) {
  1090.             while ( count < VscrnGetHeight(vmode)-(tt_status[vmode]?1:0) && ( vscrn[vmode].markbot >
  1091.                 ( vscrn[vmode].marktop + 1 + vscrn[vmode].linecount)%vscrn[vmode].linecount ) ) {
  1092.                 count++ ;
  1093.                 VscrnUnmark( vmode, vscrn[vmode].markbot, 0, MAXTERMCOL ) ;
  1094.                 if ( vscrn[vmode].cursor.x > 0 ) {
  1095.                     VscrnUnmark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x+1,
  1096.                         MAXTERMCOL );
  1097.                     }
  1098.                 }
  1099.             }
  1100.  
  1101.         if ( count < VscrnGetHeight(vmode)-(tt_status[vmode]?1:0)
  1102.              && vscrn[vmode].markbot ==
  1103.             (vscrn[vmode].marktop+1+vscrn[vmode].linecount)%vscrn[vmode].linecount ) {
  1104.             count++ ;
  1105.             VscrnUnmark( vmode, vscrn[vmode].markbot, 0, MAXTERMCOL ) ;
  1106.             if ( vscrn[vmode].cursor.x >= vscrn[vmode].lines[vscrn[vmode].markbot].markbeg ) {
  1107.                 VscrnUnmark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x+1, MAXTERMCOL ) ;
  1108.                 }
  1109.             else { /* vscrn[vmode].cursor.x < vscrn[vmode].lines[vscrn[vmode].markbot].markbeg */
  1110.                 VscrnUnmark( vmode, vscrn[vmode].markbot,
  1111.                     vscrn[vmode].lines[vscrn[vmode].markbot].markbeg+1, MAXTERMCOL ) ;
  1112.                 VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x,
  1113.                     vscrn[vmode].lines[vscrn[vmode].markbot].markbeg ) ;
  1114.                 }
  1115.             }
  1116.  
  1117.         if ( count < VscrnGetHeight(vmode)-(tt_status[vmode]?1:0) &&
  1118.             vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  1119.             count++ ;
  1120.             if ( vscrn[vmode].cursor.x == vscrn[vmode].lines[vscrn[vmode].marktop].markend ) {
  1121.                 VscrnUnmark( vmode, vscrn[vmode].marktop,
  1122.                     vscrn[vmode].lines[vscrn[vmode].marktop].markbeg+1, MAXTERMCOL ) ;
  1123.                 }
  1124.             VscrnMark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].lines[vscrn[vmode].marktop].markbeg );
  1125.             if ( vscrn[vmode].marktop != vscrn[vmode].beg )
  1126.                 VscrnMark( vmode, (vscrn[vmode].marktop-1+vscrn[vmode].linecount)%vscrn[vmode].linecount, vscrn[vmode].cursor.x,
  1127.                 MAXTERMCOL ) ;
  1128.             }
  1129.  
  1130.         while ( count < VscrnGetHeight(vmode)-(tt_status[vmode]?1:0)
  1131.                 && vscrn[vmode].marktop != vscrn[vmode].beg ) {
  1132.             count++ ;
  1133.             VscrnMark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x );
  1134.             if ( vscrn[vmode].marktop != vscrn[vmode].beg )
  1135.                 VscrnMark( vmode, (vscrn[vmode].marktop-1+vscrn[vmode].linecount)%vscrn[vmode].linecount, vscrn[vmode].cursor.x,
  1136.                     MAXTERMCOL) ;
  1137.             }
  1138.         }
  1139.  
  1140.     if ( VscrnMoveScrollTop(vmode,-(VscrnGetHeight(vmode)-(tt_status[vmode]?1:0))) < 0 ) {
  1141.         LONG oldscrolltop = VscrnGetScrollTop(vmode);
  1142.         if ( VscrnSetScrollTop(vmode,VscrnGetBegin(vmode)) < 0 )
  1143.             bleep(BP_WARN);
  1144.         else if ( oldscrolltop != VscrnGetScrollTop(vmode) )
  1145.             vscrn[vmode].cursor.y -=
  1146.             (oldscrolltop - vscrn[vmode].scrolltop + vscrn[vmode].linecount) % vscrn[vmode].linecount ;
  1147.         else vscrn[vmode].cursor.y = 0 ;
  1148.         }
  1149. }
  1150.  
  1151. void
  1152. markhomescreen(BYTE vmode )
  1153. {
  1154.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  1155.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  1156.  
  1157.     if ( markmodeflag[vmode] == marking &&
  1158.         ( curline != VscrnGetBegin(vmode) ||
  1159.         curline == VscrnGetBegin(vmode) &&
  1160.         vscrn[vmode].cursor.x != 0 ) ) {
  1161.         if ( vscrn[vmode].markbot == curline &&
  1162.             vscrn[vmode].lines[vscrn[vmode].markbot].markend == vscrn[vmode].cursor.x ) {
  1163.             while ( vscrn[vmode].markbot >
  1164.                 ( vscrn[vmode].marktop + 1 + vscrn[vmode].linecount)%vscrn[vmode].linecount ) {
  1165.                 VscrnUnmark( vmode, vscrn[vmode].markbot, 0, MAXTERMCOL ) ;
  1166.                 if ( vscrn[vmode].cursor.x > 0 ) {
  1167.                     VscrnUnmark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x+1,
  1168.                         MAXTERMCOL );
  1169.                     }
  1170.                 }
  1171.             }
  1172.  
  1173.         if ( vscrn[vmode].markbot ==
  1174.             (vscrn[vmode].marktop+1+vscrn[vmode].linecount)%vscrn[vmode].linecount ) {
  1175.             VscrnUnmark( vmode, vscrn[vmode].markbot, 0, MAXTERMCOL ) ;
  1176.             if ( vscrn[vmode].cursor.x >= vscrn[vmode].lines[vscrn[vmode].markbot].markbeg ) {
  1177.                 VscrnUnmark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x+1, MAXTERMCOL ) ;
  1178.                 }
  1179.             else { /* vscrn[vmode].cursor.x < vscrn[vmode].lines[vscrn[vmode].markbot].markbeg */
  1180.                 VscrnUnmark( vmode, vscrn[vmode].markbot,
  1181.                     vscrn[vmode].lines[vscrn[vmode].markbot].markbeg+1, MAXTERMCOL ) ;
  1182.                 VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x,
  1183.                     vscrn[vmode].lines[vscrn[vmode].markbot].markbeg ) ;
  1184.                 }
  1185.             }
  1186.  
  1187.         if ( vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  1188.             if ( vscrn[vmode].cursor.x == vscrn[vmode].lines[vscrn[vmode].marktop].markend ) {
  1189.                 VscrnUnmark( vmode, vscrn[vmode].marktop,
  1190.                     vscrn[vmode].lines[vscrn[vmode].marktop].markbeg+1, MAXTERMCOL ) ;
  1191.                 }
  1192.             VscrnMark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].lines[vscrn[vmode].marktop].markbeg );
  1193.             if ( vscrn[vmode].marktop != vscrn[vmode].beg )
  1194.                 VscrnMark( vmode, (vscrn[vmode].marktop-1+vscrn[vmode].linecount)%vscrn[vmode].linecount, vscrn[vmode].cursor.x,
  1195.                 MAXTERMCOL ) ;
  1196.             }
  1197.  
  1198.         while ( vscrn[vmode].marktop != vscrn[vmode].beg ) {
  1199.             VscrnMark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x );
  1200.             if ( vscrn[vmode].marktop != vscrn[vmode].beg )
  1201.                 VscrnMark( vmode, (vscrn[vmode].marktop-1+vscrn[vmode].linecount)%vscrn[vmode].linecount, vscrn[vmode].cursor.x,
  1202.                     MAXTERMCOL) ;
  1203.             }
  1204.  
  1205.         VscrnMark( vmode, vscrn[vmode].marktop, 0, MAXTERMCOL ) ;
  1206.         }
  1207.  
  1208.  
  1209.     if ( VscrnSetScrollTop( vmode, VscrnGetBegin(vmode) ) < 0 )
  1210.         bleep( BP_FAIL ) ;
  1211.     else {
  1212.         vscrn[vmode].cursor.x = 0 ;
  1213.         vscrn[vmode].cursor.y = 0 ;
  1214.         }
  1215. }
  1216.  
  1217. void
  1218. markendscreen( BYTE vmode )
  1219. {
  1220.    LONG curline = (VscrnGetScrollTop(vmode)+vscrn[vmode].cursor.y
  1221.       +vscrn[vmode].linecount)%vscrn[vmode].linecount ;
  1222.  
  1223.     if ( markmodeflag[vmode] == marking &&
  1224.         ( curline != VscrnGetEnd(vmode) ||
  1225.         curline == VscrnGetEnd(vmode) &&
  1226.         vscrn[vmode].cursor.x != VscrnGetWidth(vmode)-1 ) ) {
  1227.         if ( vscrn[vmode].marktop == curline &&
  1228.             vscrn[vmode].lines[vscrn[vmode].marktop].markbeg == vscrn[vmode].cursor.x ) {
  1229.             while ( vscrn[vmode].marktop <
  1230.                 ( vscrn[vmode].markbot - 1 + vscrn[vmode].linecount)%vscrn[vmode].linecount &&
  1231.                vscrn[vmode].markbot != vscrn[vmode].marktop ) {
  1232.                 VscrnUnmark( vmode, vscrn[vmode].marktop, 0, MAXTERMCOL ) ;
  1233.                 if ( vscrn[vmode].cursor.x > 0 ) {
  1234.                     VscrnUnmark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x-1 );
  1235.                     }
  1236.                 }
  1237.             }
  1238.  
  1239.         if ( vscrn[vmode].marktop ==
  1240.             (vscrn[vmode].markbot-1+vscrn[vmode].linecount)%vscrn[vmode].linecount ) {
  1241.             VscrnUnmark( vmode, vscrn[vmode].marktop, 0, MAXTERMCOL ) ;
  1242.             if ( vscrn[vmode].cursor.x <= vscrn[vmode].lines[vscrn[vmode].marktop].markend ) {
  1243.                 VscrnUnmark( vmode, vscrn[vmode].marktop, 0, vscrn[vmode].cursor.x-1 ) ;
  1244.                 }
  1245.             else { /* vscrn[vmode].cursor.x > vscrn[vmode].lines[vscrn[vmode].marktop].markend */
  1246.                 VscrnUnmark( vmode, vscrn[vmode].marktop, 0,
  1247.                     vscrn[vmode].lines[vscrn[vmode].marktop].markend-1 ) ;
  1248.                 VscrnMark( vmode, vscrn[vmode].marktop, vscrn[vmode].lines[vscrn[vmode].marktop].markend,
  1249.                     vscrn[vmode].cursor.x ) ;
  1250.                 }
  1251.             }
  1252.  
  1253.         if ( vscrn[vmode].marktop == vscrn[vmode].markbot ) {
  1254.             if ( vscrn[vmode].cursor.x == vscrn[vmode].lines[vscrn[vmode].markbot].markbeg ) {
  1255.                 VscrnUnmark( vmode, vscrn[vmode].markbot, 0,
  1256.                     vscrn[vmode].lines[vscrn[vmode].markbot].markend-1 ) ;
  1257.                 }
  1258.             VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].lines[vscrn[vmode].markbot].markend,
  1259.                 MAXTERMCOL ) ;
  1260.             if ( vscrn[vmode].markbot != vscrn[vmode].end )
  1261.                 VscrnMark( vmode, (vscrn[vmode].markbot+1)%vscrn[vmode].linecount, 0,
  1262.                     vscrn[vmode].cursor.x ) ;
  1263.             }
  1264.  
  1265.         while ( vscrn[vmode].markbot != vscrn[vmode].end-(tt_status[vmode]?1:0) ) {
  1266.             VscrnMark( vmode, vscrn[vmode].markbot, vscrn[vmode].cursor.x,
  1267.                 vscrn[vmode].lines[vscrn[vmode].markbot].width ) ;
  1268.             if ( vscrn[vmode].markbot != vscrn[vmode].end )
  1269.                 VscrnMark( vmode, (vscrn[vmode].markbot+1)%vscrn[vmode].linecount, 0,
  1270.                     vscrn[vmode].cursor.x ) ;
  1271.             }
  1272.         VscrnMark( vmode, vscrn[vmode].markbot, 0, MAXTERMCOL ) ;
  1273.         }
  1274.  
  1275.     if ( VscrnSetScrollTop( vmode, VscrnGetTop(vmode) ) < 0 )
  1276.         bleep( BP_FAIL ) ;
  1277.     else {
  1278.         vscrn[vmode].cursor.x = VscrnGetWidth(vmode)-1 ;
  1279.         vscrn[vmode].cursor.y = VscrnGetHeight(vmode)-(tt_status[vmode]?1:0)-1 ;
  1280.         }
  1281.  
  1282. }
  1283.  
  1284. void
  1285. markleftpage(BYTE vmode)
  1286. {
  1287.     if ( markmodeflag[vmode] == marking ) {
  1288.  
  1289.         }
  1290.  
  1291. }
  1292.  
  1293. void
  1294. markrightpage(BYTE vmode)
  1295. {
  1296.     if ( markmodeflag[vmode] == marking ) {
  1297.  
  1298.         }
  1299.  
  1300. }
  1301.  
  1302. void
  1303. markcopyclip( BYTE vmode, int select )
  1304. {
  1305.     if ( markmodeflag[vmode] == marking ) {
  1306.         CopyVscrnToClipboard(vmode,select);
  1307.         markmodeflag[vmode] = notmarking ;
  1308.         VscrnUnmarkAll(vmode) ;
  1309.         }
  1310.     else
  1311.         bleep( BP_FAIL ) ;
  1312. }
  1313.  
  1314. void
  1315. markselect( BYTE vmode, int select )
  1316. {
  1317.     if ( markmodeflag[vmode] == marking ) {
  1318.         VscrnSelect(vmode,select);
  1319.         markmodeflag[vmode] = notmarking ;
  1320.         VscrnUnmarkAll(vmode) ;
  1321.         }
  1322.     else
  1323.         bleep( BP_FAIL ) ;
  1324. }
  1325.  
  1326. void
  1327. markcopyhost( BYTE vmode, int select )
  1328. {
  1329.     if ( markmodeflag[vmode] == marking ) {
  1330.         CopyVscrnToKbdBuffer(vmode,select);
  1331.         markmodeflag[vmode] = notmarking ;
  1332.         VscrnUnmarkAll(vmode) ;
  1333.         }
  1334.     else
  1335.         bleep( BP_FAIL ) ;
  1336. }
  1337.  
  1338. void
  1339. markprint( BYTE vmode, int select )
  1340. {
  1341.     if ( markmodeflag[vmode] == marking ) {
  1342.         CopyVscrnToPrinter(vmode,select);
  1343.         markmodeflag[vmode] = notmarking ;
  1344.         VscrnUnmarkAll(vmode) ;
  1345.         }
  1346.     else
  1347.         bleep( BP_FAIL ) ;
  1348. }
  1349.  
  1350. #define NUM_OF_ACTIVE_LINKS 256
  1351. static unsigned short next_hyperlink_index = 1;
  1352. static hyperlink hyperlinks[NUM_OF_ACTIVE_LINKS];
  1353.  
  1354. int
  1355. hyperlink_add(int type, char * link)
  1356. {
  1357.     unsigned short idx = next_hyperlink_index % NUM_OF_ACTIVE_LINKS;
  1358.  
  1359.     hyperlinks[idx].index = next_hyperlink_index;
  1360.     next_hyperlink_index++;
  1361.     if ( hyperlinks[idx].str )
  1362.         free(hyperlinks[idx].str);
  1363.     hyperlinks[idx].str = link;
  1364.     hyperlinks[idx].type = type;
  1365.     return(hyperlinks[idx].index);
  1366. }
  1367.  
  1368. hyperlink *
  1369. hyperlink_get(int index)
  1370. {
  1371.     unsigned short idx = index % NUM_OF_ACTIVE_LINKS;
  1372.     
  1373.     if ( index == hyperlinks[idx].index )
  1374.         return &hyperlinks[idx];
  1375.     return NULL;
  1376. }
  1377. #endif /* NOLOCAL */
  1378.