home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 v2.4 Fix / W95-v2.4fix.iso / ACADWIN / ADS / WIN / SPREADSH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-14  |  10.1 KB  |  416 lines

  1. /*
  2.         SpreadSh.c
  3.  
  4.         High Level Functions for AutoCAD and Spreadsheet DDE
  5.  
  6.      ________________________________________________________________________
  7.  
  8.       (C) Copyright 1990-1995 by Autodesk, Inc.
  9.  
  10.       Permission to use, copy, modify, and distribute this software and its
  11.       documentation for any purpose and without fee is hereby granted.  
  12.  
  13.       THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 
  14.       ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF 
  15.       MERCHANTABILITY ARE HEREBY DISCLAIMED.                                
  16.      ________________________________________________________________________
  17.  
  18.  
  19.  
  20. See "Dde.txt" for more information.
  21.  
  22.  
  23.      A DDE channel must be opened using an application name and a
  24. topic, or work file, name.  See DdeInitiate.
  25. Transfers on that channel then use a string called an "item "to
  26. identify the range of data.  A DDE "item", in the case of
  27. spreadsheets, is a string referencing a range in a two dimensional
  28. array of cells.  For example, the item string "R3C1:R4C2" would refer
  29. to cells from row 3, col 1 to row 4, col 2.  Data in those cells
  30. might look like:
  31.  
  32.         10   5
  33.         20   6
  34.  
  35. and would be returned by DDE functions such as DdeRequest in
  36. pdde->pData, in the form:
  37.  
  38. "10<TAB>5<CR><LF>20<TAB>6<CR><LF>" 
  39.  
  40. This is the clipboard/DDE text format, CF_TEXT.
  41. */
  42.  
  43.  
  44.  
  45. #include "options.h"
  46.  
  47. #include <stdio.h>
  48. #include <math.h>
  49.  
  50. #include "adslib.h"
  51.  
  52. #include <process.h>
  53. #include <string.h>
  54. #include <memory.h>
  55. #include <dos.h>
  56. #include <ctype.h>
  57.  
  58. #include "winutil.h"
  59. #include "ddewin.h"
  60. #include "ddeconv.h"
  61. #include "spreadsh.h"
  62. #include "acaddefs.h"
  63.  
  64. extern ddeDATA DdeData;               /* DDE globals and defaults. */
  65.  
  66. static char *ssrow = DdeData.rowspec;
  67. static char *sscol = DdeData.colspec;
  68. static char *ssdelim = DdeData.rangespec;
  69.  
  70. /* Specify Excel or Lotus cell specification style */
  71. void
  72. AppType(int ss_type)
  73. {
  74.     DdeData.apptype = ss_type;
  75.  
  76. #ifdef DOMESTIC_US
  77.     switch (ss_type) {
  78.     case SSEXCEL:
  79.         /* R1C1:R234C4 */
  80.         strcpy(ssrow, "R");
  81.         strcpy(sscol, "C");
  82.         strcpy(ssdelim, ":");
  83.         break;
  84.  
  85.     case SSLOTUS:
  86.         /* A1..D234 */
  87.         strcpy(ssrow, "");
  88.         strcpy(sscol, "");
  89.         strcpy(ssdelim, "..");
  90.         break;
  91.  
  92.     default:
  93.         break; 
  94.     }
  95. #endif /* DOMESTIC_US */
  96. }
  97.  
  98.  
  99.  
  100. /*
  101.             Spreadsheet DDE Receive Functions
  102. */
  103.  
  104.  
  105.  
  106. /* Get an ads_real (double) request data in pReal, which
  107.    could be a pointer to an array of ads_reals.   Request 
  108.    spreadsheet data starting at Row, Col.  nRow is the
  109.    number of rows, nCol the number of columns. 
  110. */
  111. int RequestRealArray(PDDE pdde, ads_real *pReal, UINT Row, UINT Col,
  112.                  UINT nRow, UINT nCol)
  113. {
  114.     char CellItem[CELLMAX];
  115.     short Ret = FALSE;
  116.     DWORD DdeResult;
  117.     short cnt;
  118.  
  119.     CellRange(CellItem, Row, Col, nRow, nCol);
  120.     DdeResult = DdeRequest(pdde, CellItem, CF_TEXT, DATAWAIT);
  121.     if (pdde->DataSize != 0) {
  122.  
  123.         /* load array of points with converted
  124.            string data from the spreadsheet */
  125.         cnt = StrToReals(pdde->pData, pReal, nRow, nCol);
  126.         DdeFreeData(pdde);            /* free shared data */
  127.         return cnt;
  128.     }
  129.     else
  130.         return 0;
  131. }
  132.  
  133.  
  134. /* Get ads_real (double) request data in pReal. 
  135. */
  136. int ReqCellData(PDDE pdde, ads_real *pReal, UINT Row, UINT Col)
  137. {
  138.     short Ret = FALSE;
  139.     DWORD DdeResult;
  140.     char CellItem[CELLMAX];
  141.  
  142.     CellItemName(CellItem, Row, Col);
  143.     DdeResult = DdeRequest(pdde, CellItem, CF_TEXT, DATAWAIT);
  144.     if (pdde->DataSize != 0) {
  145.         *pReal = StrToReal(pdde->pData);
  146.         DdeFreeData(pdde);            /* free shared data */
  147.         Ret = TRUE;
  148.     }
  149.     return Ret;
  150. }
  151.  
  152.  
  153. /*
  154.             Spreadsheet DDE Transmit Functions
  155. */
  156.  
  157. /* Send out a range of ads_reals (doubles), in array starting
  158.    at pReal.  
  159. */
  160. int PokeRealArray(PDDE pdde, ads_real *pReal, UINT Row, UINT Col,
  161.                   UINT nRow, UINT nCol)
  162. {
  163.     char CellItem[CELLMAX];
  164.     DWORD DdeResult;
  165.     ULONG DataLen;
  166.     PHDATA CellDataStr;
  167.  
  168.     CellDataStr = RealsToStr(pReal, nRow, nCol, &DataLen);
  169.     if (!CellDataStr)
  170.         return 0;
  171.     ++DataLen;                        /* include NULL */
  172.     CellRange(CellItem, Row, Col, nRow, nCol);
  173.     DdeResult = DdePoke(pdde, CellItem, DataLen, CellDataStr, CF_TEXT);
  174.     FreeFar(CellDataStr);
  175.     return DdeResult != 0;
  176. }
  177.  
  178.  
  179. /* Send out a list of strings to a range in a spreadsheet.
  180.    TextLink is the first PLINK in a list. 
  181. */
  182. int PokeList(PDDE pdde, PLINK TextLink, UINT Row, UINT Col,
  183.               UINT nRow, UINT nCol)
  184. {
  185.     char CellItem[CELLMAX];
  186.     DWORD DdeResult;
  187.     ULONG DataLen = 0L;
  188.     UINT cCol = 0;
  189.     PHDATA CellDataStr;
  190.  
  191.     CellDataStr = DdeFormatList(TextLink, nCol, &DataLen);
  192.     CellRange(CellItem, Row, Col, nRow, nCol);
  193.     DdeResult = DdePoke(pdde, CellItem, DataLen, CellDataStr, CF_TEXT);
  194.     FreeFar(CellDataStr);
  195.     return DdeResult != 0;
  196. }
  197.  
  198.  
  199.  
  200.  
  201. /* Send out a ads_real (double). 
  202. */
  203. int PokeReal(PDDE pdde, ads_real Real, UINT Row, UINT Col)
  204. {
  205.     char CellItem[CELLMAX];
  206.     char StrData[FPSTR+1];
  207.     DWORD DdeResult;
  208.  
  209.     RealToStr(Real, StrData);
  210.     CellItemName(CellItem, Row, Col);
  211.     DdeResult = DdePokeString(pdde, CellItem, StrData);
  212.     return DdeResult != 0;
  213. }
  214.  
  215.  
  216.  
  217. /* For inserting formulas into spreadsheets:
  218.    build a cell reference string to Row, Col
  219.    (1 based).  E.g., row 3, col 1:  "=A3" 
  220. */
  221. VOID CellRef(char *CellRefStr, UINT Row, UINT Col)
  222. {
  223.     char NumStr[20];    
  224.     char *pstr = CellRefStr;
  225.  
  226.     *pstr++ = '=';
  227.     if (Col > 26) {
  228.         *pstr++ = (char)((Col / 26) - 1 + 'A');
  229.         *pstr++ = (char)((Col % 26) - 1 + 'A');
  230.     } else {
  231.         *pstr++ = (char)(Col - 1 + 'A');
  232.     }
  233.     _itoa(Row, NumStr, 10);
  234.     strcpy(pstr, NumStr);
  235. }
  236.  
  237.  
  238. /* Build DDE Item name, such as "R2C5:R11C10", from start 
  239.    row, col, number of rows, cols. 
  240. */
  241. VOID CellRange(char *CellItem, UINT Row, UINT Col,
  242.                UINT nRow, UINT nCol)
  243. {
  244.     UINT Row2, Col2;
  245.     char NumStr[20];
  246.  
  247.     Row2 = Row + nRow - 1;
  248.     Col2 = Col + nCol - 1;
  249.  
  250.     if (DdeData.apptype == SSEXCEL) {
  251.         strcpy(CellItem, ssrow);
  252.         _itoa(Row, NumStr, 10);
  253.         strcat(CellItem, NumStr);
  254.  
  255.         strcat(CellItem, sscol);
  256.         _itoa(Col, NumStr, 10);
  257.         strcat(CellItem, NumStr);
  258.         if (nRow == 1 && nCol == 1)
  259.                 return;
  260.  
  261.         strcat(CellItem, ssdelim);
  262.         strcat(CellItem, ssrow);
  263.         _itoa(Row2, NumStr, 10);
  264.         strcat(CellItem, NumStr);
  265.  
  266.         strcat(CellItem, sscol);
  267.         _itoa(Col2, NumStr, 10);
  268.         strcat(CellItem, NumStr);
  269.     } else {
  270.         CellItemName(CellItem, Row, Col);
  271.         if (nRow == 1 && nCol == 1)
  272.             return;
  273.         strcat(CellItem, ssdelim);
  274.         CellItemName(NumStr, Row2, Col2);
  275.         strcat(CellItem, NumStr);
  276.     }
  277. }
  278.  
  279.  
  280. /* For DDE Item field: build "R2C5" from Row 2, Col 5, into your
  281.    passed string, CellItemName. 
  282. */
  283. VOID CellItemName(char *CellItem, UINT Row, UINT Col)
  284. {
  285.     char NumStr[20];
  286.     char ColChar;
  287.  
  288.     if (DdeData.apptype == SSEXCEL) {
  289.         strcpy(CellItem, ssrow);
  290.         _itoa(Row, NumStr, 10);
  291.         strcat(CellItem, NumStr);
  292.  
  293.         strcat(CellItem, sscol);
  294.         _itoa(Col, NumStr, 10);
  295.         strcat(CellItem, NumStr); 
  296.     } else {
  297.         ColChar = (char)(Col-1+'A');
  298.         CellItem[0] = ColChar;
  299.         CellItem[1] = EOS;
  300.         _itoa(Row, NumStr, 10);
  301.         strcat(CellItem, NumStr);
  302.     }
  303. }
  304.  
  305.  
  306.  
  307. /* Get the row, col, number of rows, number of cols expressed in 
  308.    the RxCx:RyCy string, CellItem.  Returns TRUE if the ":" was
  309.    found, indicating a range of cells. 
  310. */
  311. int GetCellRange(char *CellItem, UINT *Row, UINT *Col,
  312.                  UINT *nRow, UINT *nCol)
  313. {
  314.     char *ptr;
  315.     char *Range2;
  316.     short Idx;
  317.     UINT ScanRow[2], ScanCol[2];
  318.     char ItemStr[41];
  319.     short RangeFlag = FALSE;
  320.     int delimlen = strlen(ssdelim);
  321.  
  322.     *Row = *Col = *nRow = *nCol = 1;
  323.     if (!CellItem || !CellItem[0])
  324.         return FALSE;
  325.     if (CellItem[0] != *ssrow && CellItem[0] != tolower(*ssrow))
  326.         return FALSE;
  327.     strzcpy(ItemStr, CellItem, 40);
  328.     ptr = ItemStr;
  329.  
  330.     /* Look for ":" or ".." the range separators. */
  331.     for ( ; *ptr != EOS; ++ptr) {
  332.         if (!strncmp(ptr, ssdelim, delimlen)) {
  333.             RangeFlag = TRUE;
  334.             Range2 = ptr+delimlen;   /* Second half of range */
  335.             *ptr = 0;
  336.             break;
  337.         }
  338.     }
  339.  
  340.     for (Idx = 0; Idx <= 1; ++Idx) {
  341.         if (Idx == 0)
  342.             ptr = ItemStr;
  343.         else
  344.             ptr = Range2;
  345.         GetCellNum(ptr, &ScanRow[Idx], &ScanCol[Idx]);
  346.         if (!RangeFlag)
  347.             break;
  348.     }
  349.  
  350.     *Row = ScanRow[0];
  351.     *Col = ScanCol[0];
  352.     if (!RangeFlag)
  353.         return FALSE;
  354.     *nRow = ScanRow[1] - ScanRow[0] + 1;
  355.     *nCol = ScanCol[1] - ScanCol[0] + 1;
  356.     return TRUE;
  357. }
  358.  
  359.  
  360.  
  361. /* Get Row and col from "R3C1" cell item string.  0 means
  362.    current row or col 
  363. */
  364. VOID GetCellNum(char *CellStr, UINT *Row, UINT *Col)
  365. {
  366.     char Chr;
  367.     char *ptr;
  368.  
  369.     ptr = CellStr;
  370.     while (Chr = *ptr++) {
  371.         if (Chr == *ssrow || Chr == *sscol) {
  372.             if (isdigit(*ptr)) {
  373.                 if (Chr == *ssrow)
  374.                     *Row = atoi(ptr);
  375.                 else if (Chr == *sscol)
  376.                     *Col = atoi(ptr);
  377.             }
  378.             else {
  379.                 if (Chr == *ssrow)
  380.                     *Row = 0;
  381.                 else if (Chr == *sscol)
  382.                     *Col = 0;
  383.             }
  384.         }
  385.     }
  386. }
  387.  
  388.  
  389.  
  390. /* Find number of rows and col's in data returned
  391.    by a cell range, such as "R3C1:R12C2" 
  392. */
  393. VOID GetCellDim(PHDATA DataStrm, UINT *nRow, UINT *nCol)
  394. {
  395.     UINT Row = 0;
  396.     UINT Col = 1;
  397.     char Chr;
  398.     short FirstRow = TRUE;
  399.  
  400.     while (Chr = *DataStrm++) {
  401.         if (Chr == CR) {
  402.             ++Row;
  403.             FirstRow = FALSE;
  404.         }
  405.         else if (FirstRow && (Chr == FldSepChr))
  406.             ++Col;
  407.     }
  408.     *nRow = Row;
  409.     *nCol = Col;
  410. }
  411.  
  412.  
  413.  
  414. /* end of file */
  415.  
  416.