home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / S12547.ZIP / MAKEBOX.C < prev    next >
Text File  |  1990-03-19  |  12KB  |  406 lines

  1. /********************************* MAKEBOX ************************\
  2. *
  3. *  VIO DBCS SAMPLE program
  4. *
  5. *  This program puts up panel containing a message into which
  6. *  the first 3 command line arguments have been substituted.
  7. *
  8. *  This program will run on any OS/2 1.2 version.
  9. *  However, most of the DBCS machinerie in it lies unused if run
  10. *  in a non-DBCS code page or on non-DBCS hardware.
  11. *
  12. *  It is therefore typical of an 'international application' which
  13. *  also contains that bit of extra code to allow it to run
  14. *  everywhere.
  15. *
  16. *  This program works so it can be run as a second process in a
  17. *  screen group, i.e. it adapts to the VIO mode, VIO code page etc
  18. *  that were set up by the first process.  Alternatively this code
  19. *  would work well in a DLL.
  20. *
  21. \******************************************************************/
  22.  
  23. #define INCL_VIO
  24. #define INCL_DOSNLS
  25. #define INCL_DOSMISC
  26. #define INCL_DOSPROCESS
  27.  
  28. #include <os2.h>
  29. #include <ctype.h>
  30. #include <stdio.h>
  31. #include "makebox.h"
  32.  
  33. BYTE   fbLead[256];          // lead byte table, initially all 0
  34.                              // (i.e. FALSE or not a lead byte)
  35.  
  36. #define fIsDbcsLead( x )  (fbLead[(x)])
  37.  
  38. #define CBMAXMSG  200       // upper bound for message text
  39.  
  40. /**  MAIN:
  41.  **
  42.  **  Construct a message panel and display
  43.  **  the arguments in a message text
  44.  **/
  45. main( argc, argv )
  46. SHORT   argc;
  47. CHAR  ** argv;
  48. {
  49.  USHORT      ib, ich, iLo, iHi;
  50.  
  51.  USHORT      usCodePage;     // code-page identifier
  52.  USHORT      usReserved=0;   // must be zero
  53.  
  54.  USHORT      cbBuf;          // length of buffer
  55.  COUNTRYCODE ctryc;          // structure for country code
  56.  CHAR        abDbcsRange[CBMAXDBCS];  // buffer for DBCS info
  57.  
  58.  CHAR        achMsgBuf[CBMAXMSG];  // return buffer for Text
  59.  USHORT      cbMsg;                // # of message bytes returned
  60.  PCHAR       apchVTable[10];       // pointer to table of pointers
  61.                                    // pointers to strings
  62.  SHORT       iTmp;
  63.  
  64.  USHORT      xLeft,                // Message box coordinates
  65.              xRight,
  66.              yTop,
  67.              yBottom;
  68.  
  69.  VIOSCROLL   vioscroll;            // VioGetState scroll info block
  70.  
  71.  VIOMODEINFO viomi;                // Video mode information
  72.  
  73.  
  74.  //   First, determine where to locate the message box.
  75.  //   Get the current Vio mode to find the number of lines on the
  76.  //   screen.
  77.  
  78.  viomi.cb = sizeof(VIOMODEINFO);
  79.  VioGetMode(&viomi, 0);
  80.  
  81.  //   note: bottom screen line is used for keybd status in DCBS
  82.  //   countries so we use VioGetState to return the size of this
  83.  //   (nonscrollable) area
  84.  
  85.  vioscroll.cb = sizeof(vioscroll);
  86.  vioscroll.type = VS_GETSCROLL;
  87.  
  88.  VioGetState((PVIOSCROLL) &vioscroll, VIOHANDLE);
  89.  
  90.  // Set Message box coordinates to stay inside screen area
  91.  
  92.  xLeft   = 10,
  93.  xRight  = viomi.col - 9,
  94.  yTop    = 5,
  95.  yBottom = viomi.row - vioscroll.cnscrl - 5;
  96.  
  97.  
  98.  //  Get Current VIO Code Page
  99.  
  100.  VioGetCp(0,                         // must be zero
  101.          &usCodePage,                // code-page identifier
  102.          VIOHANDLE);                 // video handle
  103.  
  104.  //   Get Lead Byte range (if any) for current VIO code page
  105.  //   (for SBCS code page abDbcsRange is all 0)
  106.  
  107.  ctryc.country = 0;
  108.  ctryc.codepage = usCodePage;
  109.  DosGetDBCSEv(cbBuf, (PCOUNTRYCODE) &ctryc, (PCHAR) abDbcsRange);
  110.  
  111.  //   Construct lead byte table for quick parsing of DBCS strings
  112.  
  113.  for (ib=0; ib < cbBuf && abDbcsRange[ib]; ib++){
  114.          if( ib % 1 ){
  115.                  for( ich = iLo; ich <= abDbcsRange[ib]; ich++ )
  116.                          fbLead[ich] = 1;
  117.          } else
  118.                  iLo = abDbcsRange[ib];
  119.  }
  120.  
  121.  //   Synch Process and VIO code page, so  DosGetMessage retrieves
  122.  //   characters that VIO can display.
  123.  
  124.  DosSetProcCp(usCodePage, usReserved);
  125.  
  126.  // Save screen area to be obscured by message box.
  127.  
  128.  SaveArea(yTop, xLeft, yBottom, xRight, TRUE);
  129.  
  130.  //   Retrieve frame characters
  131.  
  132.  DosGetMessage(
  133.     (PCHAR FAR *) NULL,      // pointer to table of ptrs to strings
  134.     0,                       // number of pointers in table
  135.     (PBYTE) achMsgBuf,       // buffer receiving message
  136.     CBMAXMSG,                // size of message buffer
  137.     MSG_APPL_SINGLEFRAMECHAR,// message number to retrieve
  138.     "oso001.msg",            // name of file containing message
  139.     (PUSHORT) &cbMsg);       // number of bytes in returned message
  140.  
  141.  
  142.  //   Parse the frame characters message and draw a box
  143.  
  144.  ParseFrameMsg( achMsgBuf, cbMsg);
  145.  MakeBox(yTop, xLeft, yBottom, xRight);
  146.  
  147.  // Retrieve message text; merge w/ first few arguments from argv
  148.  
  149.  argc = (argc > 4 ? 4 : argc );
  150.  for ( iTmp = 0; iTmp < argc; iTmp++) {
  151.          apchVTable[iTmp] = (PCHAR) argv[iTmp];
  152.  }
  153.  
  154.  DosGetMessage(
  155.    apchVTable,            // pointer to table of pointers to strings
  156.    argc,                  // number of pointers in table
  157.    (PCHAR) achMsgBuf,     // buffer receiving message
  158.    CBMAXMSG,              // size of message buffer
  159.    0,                     // message number to retrieve
  160.    "makebox.msg",         // name of file containing message
  161.    (PUSHORT) &cbMsg);     // number of bytes in returned message
  162.  
  163.  //   Set Cursor to beginning of message text
  164.  
  165.  VioSetCurPos(yTop + 2,               // cursor row
  166.               xLeft + 2,              // cursor column
  167.               VIOHANDLE);             // video handle
  168.  
  169.  //   Output message text
  170.  
  171.  VioWrtTTY(achMsgBuf, cbMsg, VIOHANDLE);
  172.  
  173.  
  174.  /**
  175.   **  User interaction here
  176.        .
  177.        .
  178.        .
  179.   **/
  180.  
  181.  DosSleep( 2000L );
  182.  
  183.  //   Restore screen from saved area
  184.  
  185.  SaveArea(yTop, xLeft, yBottom, xRight, FALSE);
  186.  
  187.  return 0;
  188. }
  189.  
  190. // The boxes defined here have black on red borders and a white
  191. // interior.  The attributes are ULONG so they work correctly
  192. //      with the world-wide LVB format's 3 byte attributes.
  193. //
  194.  
  195. USHORT  ausBoxChar[3][3];       // Skeleton for a box frame
  196. static ULONG aulAttr[][3] =     // Corresponding char attribute vals
  197.  
  198.                                 {  {0x40, 0x40, 0x40},
  199.          {0x40, 0x70, 0x40},
  200.          {0x40, 0x40, 0x40}
  201.         };
  202.  
  203.  
  204. /**   PARSEFRAMEMSG:
  205.  **
  206.  **   Collect the frame characters from the message and place them
  207.  **   into a skeleton 3x3 array for the box.
  208.  **/
  209.  
  210. VOID ParseFrameMsg( pchMsg, cbMsg )
  211. PCH pchMsg;
  212. USHORT cbMsg;
  213. {
  214.     sscanf( (char *)pchMsg, "%x %x %x %x %x %x %x %x",
  215.             &ausBoxChar[0][0],
  216.             &ausBoxChar[0][2],
  217.             &ausBoxChar[2][0],
  218.             &ausBoxChar[2][2],
  219.             &ausBoxChar[1][0],
  220.             &ausBoxChar[1][2],
  221.             &ausBoxChar[2][1],
  222.             &ausBoxChar[0][1]
  223.             );
  224.     ausBoxChar[1][1] = 0x20;
  225. }
  226.  
  227.  
  228. /**  MAKEBOX:
  229.  **
  230.  **  Expand Box skeleton to draw box of the desired size.  Uses VIO
  231.  **  calls exclusively in order to be portable to different H/W.
  232.  **/
  233.  
  234. VOID MakeBox(yTop, xLeft, yBottom, xRight)
  235. USHORT xLeft,                       // Box coordinates
  236.        xRight,
  237.        yTop,                        // not inclusive
  238.        yBottom;
  239. {
  240.  
  241.     static int iTimes[] = {1, 1, 1};
  242.     int i1, i2, xTemp;
  243.     USHORT usChar;
  244.  
  245.     iTimes[1] = xRight - xLeft;
  246.     xTemp = xLeft;
  247.  
  248.     // The nested loops below repeatedly draw the center row and
  249.     // center column  of the box skeleton, thereby expanding the
  250.     // box to the desired size.
  251.  
  252.     for (i1 = 0; i1 < 3; i1++)
  253.  do  {
  254.      for (i2 = 0; i2 < 3; i2++)  {
  255.  
  256.                 //  Write Frame Character
  257.  
  258.                 usChar = ausBoxChar[i1][i2];
  259.  
  260.    VioWrtNChar((PCH)&usChar, iTimes[i2],yTop, xLeft, VIOHANDLE);
  261.  
  262.                 //  Write corresponding attribute
  263.                 //  (need to write twice for DBCS frame chars)
  264.  
  265.    VioWrtNAttr((PBYTE)&aulAttr[i1][i2], iTimes[i2],
  266.                         yTop, xLeft, VIOHANDLE);
  267.                 if( fIsDbcsLead( usChar & 0xFF)){
  268.            VioWrtNAttr((PBYTE)&aulAttr[i1][i2], iTimes[i2],
  269.      yTop, xLeft, VIOHANDLE);
  270.                 }
  271.    xLeft += iTimes[i2];
  272.      }
  273.      xLeft = xTemp;
  274.      yTop++;
  275.  }  while ((i1 == 1) && (yTop < yBottom));
  276.  
  277. } /* end MakeBox */
  278.  
  279.  
  280. /** SAVEAREA:
  281.  **
  282.  ** This function saves and restores the area of the screen that
  283.  ** will be obscured by our message panel.  Care is taken that any
  284.  ** DBCS chars which might be straddling the edges of the rectangle
  285.  ** are saved and restored correctly.
  286.  **
  287.  ** This problem may exist if the rectangle to be saved doesn't
  288.  ** extend to the screen edge.  It is handled by saving an extra
  289.  ** cell on each side. The saved buffer will contain the full DBCS
  290.  ** character for for any DBCS charactrers that were straddling the
  291.  ** initial rectangle.
  292.  **
  293.  ** Before restoring we need to know which of the extra cells
  294.  ** contain such halves of DBCS characters necessary for completion.
  295.  ** VioCheckCharType is used to check the cell in the video buffer.
  296.  **/
  297. VOID SaveArea(yTop, xLeft, yBottom, xRight, fSave)
  298. USHORT xLeft,                // area coordinates
  299.        xRight,
  300.        yTop,                 // not inclusive
  301.        yBottom;
  302. BOOL fSave;
  303. {
  304.  
  305.     static SEL selArea;      // Selector for saved segment
  306.     static PBYTE pbArea;     // Pointer to saved screen area
  307.  
  308.     PBYTE pbLine;            // Pointer to line being drawn
  309.     SHORT cbmax, cbCur, xCur, cbCell, cbArea;
  310.     VIOMODEINFO viomi;       // Video mode information
  311.  
  312.     USHORT usType;           // Cell type
  313.  
  314.     //Get the current Vio mode to find out whether we have 1 or 3
  315.     //attribute bytes per cell. Set the size of the saved area
  316.     //accordingly;
  317.  
  318.     viomi.cb = sizeof(VIOMODEINFO);
  319.     VioGetMode(&viomi, 0);
  320.     cbCell = viomi.attrib+1;
  321.  
  322.     //   Calculate maximum number of bytes per line to be saved
  323.  
  324.     cbmax = (xRight - xLeft + 3) * cbCell;
  325.  
  326.     //   Allocate buffer to hold saved area
  327.  
  328.     if( fSave ){
  329.         cbArea = (yBottom - yTop + 1) * cbmax;
  330.  
  331.         DosAllocSeg(cbArea,          //bytes to allocate
  332.                 &selArea,            //address of selector
  333.                 SEG_NONSHARED);      //sharing flag
  334.     }
  335.     pbArea = MAKEP(selArea, 0);      //convert selector to pointer
  336.  
  337.     do  {
  338.         //  Number of bytes per line to be saved and
  339.         //  starting offset for this line
  340.  
  341.         cbCur = cbmax;
  342.         pbLine = pbArea + (yBottom - yTop) * cbmax;
  343.  
  344.         //  Extend area to be saved by 1 col Left & Right
  345.         //  (unless we are already at the edge of the screen)
  346.  
  347.         if(xLeft )
  348.                  xCur = xLeft-1;
  349.         else
  350.                  xCur=xLeft, cbCur-= cbCell;
  351.  
  352.         if ( xRight == viomi.col )
  353.                 cbCur-= cbCell;
  354.  
  355.         if( fSave ){
  356.  
  357.              //  Save one line
  358.  
  359.       VioReadCellStr(pbLine,(PUSHORT) &cbCur,yTop,xCur,VIOHANDLE);
  360.  
  361.         } else {
  362.  
  363.              //  Inspect the byte left of the obscured area:
  364.              //  If it's a trail byte, our saved string
  365.              //  begins with this trail byte which is illegal.
  366.              //  Advance our string pointer and start column by one.
  367.  
  368.              if(xLeft > xCur){
  369.                  VioCheckCharType( (PUSHORT) &usType, yTop, xCur,
  370.                                    VIOHANDLE);
  371.                  if( usType == VCC_DBCS2NDHALF ) {
  372.  
  373.                     //  skip trail byte on write
  374.  
  375.                     xCur = xLeft;
  376.                     cbCur -= cbCell;
  377.                     pbLine += cbCell;
  378.                  }
  379.              }
  380.  
  381.              //  As above, we cannot end a write on a lead byte.
  382.  
  383.              if ( xRight < viomi.col ){
  384.                  VioCheckCharType( (PUSHORT) &usType, yTop, xRight+1,
  385.                                    VIOHANDLE);
  386.                  if( usType == VCC_DBCS1STHALF )
  387.  
  388.                        //   don't end write on lead byte
  389.  
  390.                        cbCur-= cbCell;
  391.              }
  392.  
  393.              //  Restore one line
  394.  
  395.       VioWrtCellStr(pbLine, cbCur, yTop, xCur, VIOHANDLE);
  396.  }
  397.     }  while (++yTop <= yBottom);
  398.  
  399.     //   Free memory after restore
  400.  
  401.     if( !fSave ){
  402.         DosFreeSeg( selArea );
  403.     }
  404.  
  405. }  /* end SaveArea */
  406.