home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p024 / 12.img / ADS3.LIB / DRAGGER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-12  |  20.8 KB  |  687 lines

  1. /* Next available MSG number is  21 */
  2.  
  3. /***************************************************************************
  4.    Module Name:  dragger.c
  5.  
  6.    Description:Another Sample ADS application
  7.  
  8.    Author     :
  9.                  Autodesk, Inc.
  10.                  2320 Marinship Way
  11.                  Sausalito, CA. 94965
  12.                  (415)332-2344
  13.  
  14.       ¬⌐┼v (C) 1990-1992  Autodesk ñ╜Ñq
  15.  
  16.       Ñ╗│n┼ΘºK╢O¿╤▒z╢iªµÑ⌠ª≤Ñ╬│~╗▌¿D¬║½■¿⌐íB¡╫º∩ñ╬╡oªµ, ª²¼O░╚╜╨┐φ┤`ñU¡z
  17.       ¡∞½h :
  18.  
  19.       1)  ñWªC¬║¬⌐┼v│qºi░╚╗▌ÑX▓{ªb¿Cñ@Ñ≈½■¿⌐∙╪íC
  20.       2)  ¼█├÷¬║╗í⌐·ñσÑ≤ñ]Ñ▓╢╖⌐·╕ⁿ¬⌐┼v│qºiñ╬Ñ╗╢╡│\Ñi│qºiíC
  21.  
  22.       Ñ╗│n┼Θ╢╚┤ú¿╤º@¼░└│Ñ╬ñW¬║░╤ª╥, ª╙Ñ╝┴n⌐·⌐╬┴⌠ºtÑ⌠ª≤½O├╥; ╣∩⌐≤Ñ⌠ª≤»S«φ
  23.       Ñ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºtÑX¿π¬║½O├╥, ªbª╣ñ@╖ºñ⌐ÑHº_╗{íC
  24.  
  25.  
  26.  
  27.     Function Entry Points:
  28.         void
  29.         main(argc, argv)
  30.         int    argc;              [Number of argument passed in cmd line]
  31.         char   *argv[];           [Array of pointers to arguments]
  32.  
  33.     Exported ADS Functions
  34.         TESTDRAGGEN               [Test the ADS_DRAGGEN function]
  35.  
  36.     Modification History:
  37.         Feb 11 1992 - bcm - original creation
  38.  
  39.     Notes and restrictions on use:
  40.  
  41.  
  42. ***************************************************************************/
  43.  
  44. /**************************************************************************/
  45. /*  MODULE NAME  */
  46. /**************************************************************************/
  47. #define    DRAGGER
  48.  
  49. /****************************************************************************/
  50. /*  DEFINES  */
  51. /****************************************************************************/
  52. #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
  53.  
  54. /**************************************************************************/
  55. /*  TYPEDEFS  */
  56. /**************************************************************************/
  57. /* ADS Function Table */
  58. typedef struct {
  59.     char    *name;
  60.     int     (*fptr)();
  61. } ftblent;
  62.  
  63. typedef struct resbuf rbtype;
  64.  
  65. /**************************************************************************/
  66. /*  INCLUDES  */
  67. /**************************************************************************/
  68.  
  69. #include <stdio.h>
  70. #include <math.h>
  71. #include <memory.h>
  72. #include "adslib.h"
  73. #include "ol_errno.h"
  74.  
  75. /****************************************************************************/
  76. /*  LOCAL FUNCTION FORWARD DECLARATIONS  */
  77. /****************************************************************************/
  78. int     testdraggen();
  79. int     dragsampler _((ads_point pt, ads_matrix mat));
  80.  
  81.  
  82. /**************************************************************************/
  83. /*  GLOBAL VARIABLES  */
  84. /**************************************************************************/
  85. /* Table of ADS functions */
  86. ftblent exfun[] = {
  87.             {/*MSG0*/"C:TESTDRAGGEN", testdraggen},
  88.         };
  89.  
  90. /* Table of keyword functions */
  91. char *kwtab[] = {
  92.                   /*MSG0*/"MXYZ",
  93.                   /*MSG0*/"SXYZ",
  94.                   /*MSG0*/"RX",
  95.                   /*MSG0*/"RY",
  96.                   /*MSG0*/"RZ",
  97.                   /*MSG0*/"NOP",
  98.                   /*MSG0*/"EXIT",
  99.                  };
  100.  
  101. #define MXYZ 0
  102. #define SXYZ 1
  103. #define RX   2
  104. #define RY   3
  105. #define RZ   4
  106. #define NOP  5
  107. #define EXIT 6
  108.  
  109. int       KwIndex = NOP;              /* Index into kwtab */
  110. ads_point Base;                       /* Base point for xform */
  111.  
  112. ads_matrix     CTM;                   /* Current Transformation Matrix */
  113. /**************************************************************************/
  114. /*  EXTERNAL FUNCTION DECLARATIONS  */
  115. /**************************************************************************/
  116. extern char *strcat();
  117. extern int  strcmp();
  118.  
  119. /**************************************************************************/
  120. /*  EXTERNAL VARIABLE DECLARATIONS  */
  121. /**************************************************************************/
  122.  
  123. /****************************************************************************/
  124. /*  LOCAL FUNCTION DECLARATIONS  */
  125. /****************************************************************************/
  126.  
  127. /******************************************************************************/
  128. /*.doc geterrno(internal) */
  129. /*+
  130.     This function is called to obtain the value of the AutoCAD system
  131.     variable ERRNO and return it as a result.
  132. -*/
  133. /******************************************************************************/
  134. int
  135. /*FCN*/geterrno()
  136. {
  137.     rbtype errval;
  138.  
  139.     ads_getvar(/*MSG0*/"ERRNO", &errval);
  140.  
  141.     return errval.resval.rint;
  142. }
  143.  
  144. /******************************************************************************/
  145. /*.doc funcload(internal) */
  146. /*+
  147.     This function is called to define all function names in the ADS
  148.     function table.  Each named function will be callable from lisp or
  149.     invokable from another ADS application.
  150. -*/
  151. /******************************************************************************/
  152. int
  153. /*FCN*/funcload()
  154. {
  155.     int i;
  156.  
  157.     for (i = 0; i < ELEMENTS(exfun); i++) {
  158.         if (!ads_defun(exfun[i].name, i))
  159.             return RTERROR;
  160.     }
  161.  
  162.     return RTNORM;
  163. }
  164.  
  165. /******************************************************************************/
  166. /*.doc funclunoad(internal) */
  167. /*+
  168.     This function is called to undefine all function names in the ADS
  169.     function table.  Each named function will be removed from the
  170.     AutoLISP hash table.
  171. -*/
  172. /******************************************************************************/
  173. int
  174. /*FCN*/funcunload()
  175. {
  176.     int i;
  177.  
  178.     /* Undefine each function we defined */
  179.  
  180.     for (i = 0; i < ELEMENTS(exfun); i++) {
  181.         ads_undef(exfun[i].name,i);
  182.     }
  183.  
  184.     return RTNORM;
  185. }
  186. /******************************************************************************/
  187. /*.doc dofun(internal) */
  188. /*+
  189.     This function is called to invoke the function which has the
  190.     registerd function code that is obtained from  ads_getfuncode.  The
  191.     function will return RTERROR if the function code is invalid, or
  192.     RSERR if the invoked function fails to return RTNORM.  The value
  193.     RSRSLT will be returned if the function code is valid and the
  194.     invoked subroutine returns RTNORM.
  195. -*/
  196. /******************************************************************************/
  197. int
  198. /*FCN*/dofun()
  199. {
  200.     int val;
  201.  
  202.     if ((val = ads_getfuncode()) < 0 || val > ELEMENTS(exfun))
  203.         return RTERROR;
  204.  
  205.     return ((*exfun[val].fptr)() == RTNORM ? RSRSLT:RSERR);
  206. }
  207.  
  208. /******************************************************************************/
  209. /*.doc main(internal) */
  210. /*+
  211.     This is the main entry point for the ADS application.  All ADS
  212.     requests will be dispatched from this function.  This is your
  213.     standard ADS dispatch loop.
  214. -*/
  215. /******************************************************************************/
  216. void
  217. /*FCN*/main(argc,argv)
  218. int argc;
  219. char *argv[];
  220. {
  221.     short scode = RSRSLT;          /* Normal result code (default) */
  222.     int   stat;
  223.  
  224.     ads_init(argc, argv);          /* Initiate communication with AutoLISP */
  225.  
  226.     for ( ;; ) {                   /* Request/Result loop */
  227.  
  228.         if ((stat = ads_link(scode)) < 0) {
  229.             printf(/*MSG1*/"DRAGGER: Ñ╤ ads_link() ╢╟ª^¬║ñú¿╬¬¼║A = %d\n", stat);
  230.             fflush(stdout);
  231.             exit(1);
  232.         }
  233.  
  234.         scode = RSRSLT;           /* Reset result code */
  235.  
  236.         switch (stat) {
  237.  
  238.         case RQXLOAD:             /* Load & define functions */
  239.             scode = funcload() ? -RSRSLT : -RSERR;
  240.             break;
  241.  
  242.         case RQXUNLD:             /* Unload functions */
  243.             scode = funcunload() ? -RSRSLT : -RSERR;
  244.             ads_printf(/*MSG2*/"─└⌐±íC\n");
  245.             break;
  246.  
  247.         case RQSUBR:             /* Handle request for external function */
  248.             dofun();
  249.             break;
  250.  
  251.         default:
  252.             break;
  253.         }
  254.     }
  255. }
  256.  
  257. /******************************************************************************/
  258. /*.doc ads_mat_ident(internal) */
  259. /*+
  260.     Set up an identity matrix.
  261. -*/
  262. /******************************************************************************/
  263. void
  264. /*FCN*/ads_mat_ident(matrix)
  265. ads_matrix matrix;
  266. {
  267.     extern ads_matrix ads_identmat;
  268.     memcpy(matrix, ads_identmat, sizeof(ads_matrix));
  269. }
  270.  
  271. /******************************************************************************/
  272. /*.doc ads_subvec(internal) */
  273. /*+
  274.     Subtract two ads_points.
  275. -*/
  276. /******************************************************************************/
  277. void
  278. /*FCN*/ads_subvec(ap, bp, dp)
  279. ads_point ap, bp;
  280. ads_point dp;
  281. {
  282.     dp[X] = ap[X] - bp[X];
  283.     dp[Y] = ap[Y] - bp[Y];
  284.     dp[Z] = ap[Z] - bp[Z];
  285. }
  286.  
  287.  
  288. /******************************************************************************/
  289. /*.doc ads_fabsv(internal) */
  290. /*+
  291.     Get normal of a vector.
  292. -*/
  293. /******************************************************************************/
  294. ads_real
  295. /*FCN*/ads_fabsv(ap)
  296. ads_point ap;
  297. {
  298.     return sqrt(ap[X] * ap[X] + ap[Y] * ap[Y] + ap[Z] * ap[Z]);
  299. }
  300.  
  301. /******************************************************************************/
  302. /*.doc ads_dist(internal) */
  303. /*+
  304.     Calculate distance between two points.
  305. -*/
  306. /******************************************************************************/
  307. ads_real
  308. /*FCN*/ads_dist(p1, p2)
  309. ads_point p1, p2;
  310. {
  311.     ads_point pd;
  312.  
  313.     ads_subvec(p1, p2, pd);
  314.     return ads_fabsv(pd);
  315. }
  316.  
  317.  
  318. /******************************************************************************/
  319. /*.doc ads_mat_ixlate(internal) */
  320. /*+
  321.     Set up a translation matrix.
  322. -*/
  323. /******************************************************************************/
  324. void
  325. /*FCN*/ads_mat_ixlate(vec, result)
  326. ads_point vec;
  327. ads_matrix   result;
  328. {
  329.     ads_mat_ident(result);
  330.     result[X][T] = - vec[X];
  331.     result[Y][T] = - vec[Y];
  332.     result[Z][T] = - vec[Z];
  333. }
  334.  
  335. /******************************************************************************/
  336. /*.doc ads_mat_rot(internal) */
  337. /*+
  338.     Generate a matrix that rotates about a given axis.
  339. -*/
  340. /******************************************************************************/
  341. void
  342. /*FCN*/ads_mat_rot(angle, axis, m)
  343. ads_real angle;
  344. int axis;
  345. ads_matrix m;
  346. {
  347.     int axp1, axp2;
  348.  
  349.     axp1 = (axis + 1) % 3;
  350.     axp2 = (axis + 2) % 3;
  351.     ads_mat_ident(m);
  352.     m[axp1][axp1] = m[axp2][axp2] = cos(angle);
  353.     m[axp1][axp2] = -(m[axp2][axp1] = sin(angle));
  354. }
  355.  
  356. /******************************************************************************/
  357. /*.doc ads_mat_scale(internal) */
  358. /*+
  359.     Generate a matrix that scales the 3 axes by given amounts.
  360. -*/
  361. /******************************************************************************/
  362. void
  363. /*FCN*/ads_mat_scale(xscale, yscale, zscale, m)
  364. ads_real xscale, yscale, zscale;
  365. ads_matrix m;
  366. {
  367.     ads_mat_ident(m);
  368.     m[X][X] = xscale;
  369.     m[Y][Y] = yscale;
  370.     m[Z][Z] = zscale;
  371. }
  372.  
  373. /******************************************************************************/
  374. /*.doc ads_mat_x_pt(internal) */
  375. /*+
  376.     Multiply matrix by a given point.  Note that it does translation.
  377. -*/
  378. /******************************************************************************/
  379. void
  380. /*FCN*/ads_mat_x_pt(mat, pin, pout)
  381. ads_matrix mat;
  382. ads_point pin;
  383. ads_point pout;
  384. {
  385.     int i;
  386.     ads_point temp;
  387.  
  388.     for (i = X; i <= Z; i++)
  389.         temp[i] = mat[i][X] * pin[X] +
  390.                   mat[i][Y] * pin[Y] +
  391.                   mat[i][Z] * pin[Z] +
  392.                   mat[i][T];
  393.     memcpy(pout, temp, sizeof(ads_point));
  394. }
  395.  
  396. /******************************************************************************/
  397. /*.doc ads_mat_x_vec(internal) */
  398. /*+
  399.     Multiply matrix by a given vector.  Note that it does NO translation.
  400. -*/
  401. /******************************************************************************/
  402. void
  403. /*FCN*/ads_mat_x_vec(mat, pin, pout)
  404. ads_matrix mat;
  405. ads_point pin;
  406. ads_point pout;
  407. {
  408.     int i;
  409.     ads_point temp;
  410.  
  411.     for (i = X; i <= Z; i++)
  412.         temp[i] = mat[i][X] * pin[X] +
  413.                   mat[i][Y] * pin[Y] +
  414.                   mat[i][Z] * pin[Z];
  415.     memcpy(pout, temp, sizeof(ads_point));
  416. }
  417.  
  418. /******************************************************************************/
  419. /*.doc ads_mat_x_mat(internal) */
  420. /*+
  421.     Multiply two matrices.  Any or all arguments may point to the same array.
  422. -*/
  423. /******************************************************************************/
  424. void
  425. /*FCN*/ads_mat_x_mat(mata, matb, matout)
  426. ads_matrix mata;
  427. ads_matrix matb;
  428. ads_matrix matout;
  429. {
  430.     ads_matrix t;
  431.     int i, j, k;
  432.     ads_real sum;
  433.  
  434.     for (i = 0; i < 4; i++)
  435.         for (j = 0; j < 4; j++) {
  436.             sum = 0.0;
  437.             for (k=0; k<4; k++)
  438.                 sum += mata[i][k] * matb[k][j];
  439.             t[i][j] = sum;
  440.         }
  441.     memcpy(matout, t, sizeof(ads_matrix));
  442. }
  443.  
  444.  
  445. /******************************************************************************/
  446. /*.doc dragsampler(internal) */
  447. /*+
  448.     ADS_DRAGGEN sampler function.  This function is called every time the
  449.     digitizer is moved.  It receives two arguments, the first is pt, and
  450.     the second is mat.  The argument pt is the current digitizer location,
  451.     and the arguemnt mat is the transformation matrix which is being used
  452.     by AutoCAD to display the current selection set of objects.
  453.  
  454.     The global KwIndex is an integer variable which contains a code
  455.     representing the current drag mode.  The possible values are MXYZ,
  456.     SXYZ, RX, RY, RZ, NOP, and EXIT.  This variable is set in the function
  457.     testdraggen.
  458.  
  459.     The global CTM is set to the value of the argument mat before
  460.     returning from the dragsampler.  This variable is used by testdraggen
  461.     when performing an ADS_XFORSS call.
  462. -*/
  463. /******************************************************************************/
  464. int
  465. /*FCN*/dragsampler(pt, mat)
  466. ads_point    pt;
  467. ads_matrix        mat;
  468. {
  469.  
  470.     ads_real        D;
  471.     ads_real        angle;
  472.     ads_point       tp;
  473.     int             axis;
  474.  
  475.     switch(KwIndex) {
  476.     case MXYZ:
  477.         /* generate translation matrix */
  478.         ads_subvec(pt, Base, tp);
  479.         ads_mat_x_vec(mat, tp, tp);
  480.         mat[X][T] = tp[X];
  481.         mat[Y][T] = tp[Y];
  482.         mat[Z][T] = tp[Z];
  483.  
  484.         break;
  485.  
  486.     case SXYZ:
  487.         /* generate uniformly scaled matrix */
  488.         D = ads_dist(pt, Base);
  489.         if (D < .0001)
  490.             D = .0001;
  491.         ads_mat_scale(D,D, D, mat);
  492.  
  493.         /* calculate new translation point */
  494.         ads_mat_x_vec(mat, Base, tp);
  495.         ads_subvec(Base, tp, tp);
  496.         mat[X][T] = tp[X];
  497.         mat[Y][T] = tp[Y];
  498.         mat[Z][T] = tp[Z];
  499.  
  500.         break;
  501.  
  502.     case RX:
  503.     case RY:
  504.     case RZ:
  505.         switch (KwIndex) {
  506.         case RX:
  507.             axis = X;
  508.             break;
  509.         case RY:
  510.             axis = Y;
  511.             break;
  512.         case RZ:
  513.             axis = Z;
  514.             break;
  515.         }
  516.  
  517.  
  518.         /* calculate angle of line between LastPoint and tp */
  519.         ads_subvec(pt, Base, tp);
  520.         angle = ads_angle(Base, pt);
  521.  
  522.         /* generate rotation matrix about axis */
  523.         ads_mat_rot(angle, axis, mat);
  524.  
  525.         /* calculate new translation point */
  526.         ads_mat_x_vec(mat, Base, tp);
  527.         ads_subvec(Base, tp, tp);
  528.         mat[X][T] = tp[X];
  529.         mat[Y][T] = tp[Y];
  530.         mat[Z][T] = tp[Z];
  531.  
  532.         break;
  533.     case EXIT:
  534.         return RTCAN;
  535.     case NOP:
  536.     default:
  537.         return RTNONE;
  538.     }
  539.  
  540.     memcpy(CTM, mat, sizeof(ads_matrix));
  541.     return RTNORM;
  542. }
  543.  
  544. /******************************************************************************/
  545. /*.doc testdraggen(internal) */
  546. /*+
  547.     This function is called from dofun as a result of an RQSUBR
  548.     request being sent to the main dispatch loop.
  549.  
  550.     It instructs the user to select the set of entitis that will be
  551.     dragged by the ads_draggen function.  The selection is obtained by
  552.     performing an ads_ssget Crossing.  If a selection set contains one
  553.     or more entities, then the user will be instructed to move the
  554.     mouse for dragging the object(s), or enter a keyword to modify the
  555.     behavior of the dragging operation.
  556.  
  557.     The list of keywords is obtained from the keytable, and each
  558.     keyword in the table has a different affect on the sampler function.
  559.     The sampler will perform the transformation indicated by the value of
  560.     KwIndex.
  561.  
  562.     Once a valid point has been selected, this test function will
  563.     attempt to transform the selection set of entities in the database.
  564.     The transformation will not work if the transformation matrix
  565.     contains a non uniform scale.
  566.  
  567.     The return value for this function is the last value in rc.
  568. -*/
  569. /******************************************************************************/
  570. int
  571. /*FCN*/testdraggen()
  572. {
  573.     int         x;
  574.     int         rc;
  575.     long        slen;
  576.     ads_point   pt1;
  577.     ads_point   pt2;
  578.     ads_point   pt3;
  579.     ads_name    ssname;
  580.     rbtype      *args;
  581.     char        tstr[512];
  582.     char        kwlist[128];
  583.     char        draggenprompt[512];
  584.     int         cur;
  585.  
  586.     args = ads_getargs();
  587.     ads_mat_ident(CTM);
  588.     cur = 0;
  589.     /* Build the key word list from the key word table */
  590.     kwlist[0] = '\0';
  591.     for (x = 0; x < ELEMENTS(kwtab); x++) {
  592.         if (x != 0)
  593.             strcat(kwlist, /*MSG0*/" ");
  594.         strcat(kwlist, kwtab[x]);
  595.     }
  596.  
  597.     /* Select entities for DRAGGEN test */
  598.     ads_printf(/*MSG3*/"\n░⌡ªµíuads_draggenív┤·╕╒\n");
  599.     if (args != NULL) {
  600.         ads_printf(/*MSG4*/"ñú╗▌¡níuñ▐╝╞ívíC\n");
  601.         ads_retlist(args);
  602.     }
  603.     KwIndex = NOP;
  604.     ads_printf(/*MSG5*/"┐∩╛▄╣w│╞⌐∞ñ▐¬║¬½┼Θ\n");
  605.     if (ads_getpoint(NULL, /*MSG6*/"\n▓─ñ@¿ñ┬I:", pt1) == RTNORM) {
  606.         if (ads_getcorner(pt1, /*MSG7*/"\nÑtñ@¿ñ┬I:", pt2) == RTNORM) {
  607.             ads_ssget(/*MSG0*/"C", pt1, pt2, NULL, ssname);
  608.             rc = ads_sslength(ssname, &slen);
  609.             if (rc != RTNORM || slen == 0L)
  610.                 return RTNORM;
  611.             ads_getpoint(NULL, /*MSG8*/"\n░≥╖╟┬I", Base);
  612.             sprintf(draggenprompt, /*MSG9*/"\n▓╛░╩íu╖╞╣½ív⌐╬┐ΘñJ :(%s)", kwlist);
  613.             do {
  614.                 ads_initget(RSG_NONULL|RSG_OTHER, kwlist);
  615.                 rc = ads_draggen(ssname,
  616.                                  draggenprompt,
  617.                                  cur,
  618.                                  dragsampler,
  619.                                  pt3);
  620.                 switch (rc) {
  621.                 case RTKWORD:
  622.                     ads_getinput(tstr);
  623.                     rc = RTNORM;
  624.                     for (x = 0; x < ELEMENTS(kwtab); x++) {
  625.                         if (strcmp(tstr, kwtab[x]) == 0) {
  626.                             KwIndex = x;
  627.                             ads_mat_ident(CTM);
  628.                             break;
  629.                         }
  630.                     }
  631.                     if (x >= ELEMENTS(kwtab))
  632.                         ads_printf(/*MSG10*/"\níu%sív¼░╡L«─¬║íu├÷┴ΣªrívíC", tstr);
  633.                     break;
  634.                 case RTSTR:
  635.                     ads_getinput(tstr);
  636.                     rc = RTNORM;
  637.                     ads_printf(/*MSG11*/"Ñ╬ñß┐ΘñJ :%s\n", tstr);
  638.                     break;
  639.                 case RTNORM:
  640.                     rc = ads_xformss(ssname, CTM);
  641.                     if (rc != RTNORM)
  642.                         switch(geterrno()) {
  643.                         case OL_ESSVALID:
  644.                             ads_printf(/*MSG12*/"\n┐∩╢░╡L«─íC\n");
  645.                             break;
  646.                         case OL_EDELENT:
  647.                             ads_printf(/*MSG13*/"\níu┐∩╢░ívºtª│ñwíuºR░úív¬║╣╧ñ╕íC\n");
  648.                             break;
  649.                         case OL_EMODSEQ:
  650.                             ads_printf(/*MSG14*/"\n╡L¬k┬α╕míuSEQENDív╣╧ñ╕íC\n");
  651.                             break;
  652.                         case OL_ERGBUSY:
  653.                             ads_printf(/*MSG15*/"\n╢iªµ╜╞┬°¬║íu¡½Ñ═ívíC\n");
  654.                             break;
  655.                         case OL_EMMVPORT:
  656.                             ads_printf(/*MSG16*/"\n╡L¬k┬α╕míu╡°╡íív╣╧ñ╕íC\n");
  657.                             break;
  658.                         case OL_EMMLL:
  659.                             ads_printf(/*MSG17*/"\n╡L¬k┬α╕míu┬Ω┼@╣╧╝hívñW¬║╣╧ñ╕íC\n");
  660.                             break;
  661.                         case OL_EXFMVALID:
  662.                             ads_printf(/*MSG18*/"\níu┬α╕m»x░}ív╡L«─íC\n");
  663.                             break;
  664.                         }
  665.  
  666.                     ads_mat_x_pt(CTM, Base, Base);
  667.                     ads_mat_ident(CTM);
  668.                     break;
  669.                 case RTCAN:
  670.                     ads_printf(/*MSG19*/"\níu⌐∞ñ▐ívñwñññε\n");
  671.                     break;
  672.                 case RTERROR:
  673.                 default:
  674.                     ads_printf(/*MSG20*/"\níu⌐∞ñ▐ívº@╖~Ñó▒╤\n");
  675.                     break;
  676.                 }
  677.             } while (rc == RTNORM);
  678.             /* release the selection set */
  679.             ads_ssfree(ssname);
  680.         }
  681.     }
  682.  
  683.  
  684.     return RTNORM;
  685. }
  686.  
  687.