home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p024 / 12.img / ADS2.LIB / SAGET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-17  |  70.1 KB  |  2,575 lines

  1. /*****************************************************************************
  2.       SAGET.C
  3.       ¬⌐┼v (C) 1988-1992  Autodesk ñ╜Ñq
  4.  
  5.       Ñ╗╡{ªíñwÑ╤ Autodesk ñ╜Ñq╡∙ÑU¬⌐┼v, ╢╚⌐≤ñU¡z▒í¬pñUÑi▒┬╗P▒zíu│\ÑiívíC
  6.       ╗╒ñUñú▒oÑHÑ⌠ª≤º╬ªí╡oªµ⌐╬ÑX¬⌐ª╣╡{ªí¬║íu¡∞⌐l╜Xív; ª²ñ╣│\▒zªb»S⌐w¡lÑ═
  7.       ¬║ñuº@ñW╡▓ªXª╣╡{ªí¬║íuÑ╪¬║╜Xív¿╧Ñ╬íCª│├÷│o├■¡lÑ═ñuº@¬║▒°Ñ≤ªpñU:
  8.  
  9.       ( i)  │]¡pñW╗Pñuº@ñW¼╥»┬║Θ░w╣∩ Autodesk ñ╜Ñq¬║▓ú½~íC
  10.       (ii)  ╕ⁿª│íu¬⌐┼v  (C) 1988-1992  Autodesk ñ╜Ñqív¬║¬⌐┼v│qºiíC
  11.  
  12.  
  13.  
  14.       AUTODESKñ╜Ñq┤ú¿╤ª╣╡{ªí╢╚¿╤º@íu├■ªⁿív¬║░╤ª╥, ª╙ÑBñú▒╞░úª│Ñ⌠ª≤┐∙╗~¬║
  15.       Ñi»αíCAUTODESKñ╜Ñq»Sª╣º_╗{Ñ⌠ª≤»S⌐wÑ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºt
  16.       ÑX¿π¬║½O├╥íCAUTODESKñ╜ÑqªP«╔ÑτñúÑX¿πª╣╡{ªí░⌡ªµ«╔ñ@⌐wñú╖|íuññ┬_ív⌐╬
  17.       íuº╣Ñ■╡L╗~ív¬║½O├╥íC
  18.  
  19.  
  20.   Description: Library of extended ads_getxxx() functions. These functions
  21.                behave exactly the same as their original ADS counterparts
  22.                but provide:
  23.  
  24.                - AutoLISP input redirection
  25.                - supporting 'CAL (Geometry Calculator) command
  26.                - options 'CP and Baseplane
  27.  
  28.                The library also contains some new functions for entering
  29.                an axis and a plane etc.
  30.  
  31.   Notes:
  32.  
  33.   See the AME R2 manual for the description of the AutoLISP support
  34.   and the 'CP and Baseplane options. The 'CAL command (Geometry Calculator)
  35.   is described in the "AutoCAD Extras" manual.
  36.  
  37.   You must call sa_init_input() at the beginning of each ADS command,
  38.   before using any of the sa_getxxx() functions. This function initializes
  39.   some variables and reads the list of result buffers passed to the ADS
  40.   command via AutoLISP. It also reads the implied selection set.
  41.  
  42.   Global variable 'lisp_input' is set to TRUE if the input is read from
  43.   AutoLISP and FALSE if the input is read from the keyboard.
  44.  
  45.   If an error occurs during the input from AutoLISP, global variable
  46.   'lisp_error' is set to TRUE and all subsequent calls to sa_getxx()
  47.   functions will do nothing and just return RTERROR. This is to disable
  48.   the input of other parameters from AutoLISP if something failed before.
  49.  
  50.   You must use sa_initget() and sa_getinput() with sa_getxxx()
  51.   functions, not the standard ads_initget() and ads_getinput().
  52.  
  53.   All the functions return standard ADS return codes, i.e. RTNORM,
  54.   RTNONE, RTERROR, RTCAN, RTKWORD, RTSTRING etc.
  55.  
  56. *****************************************************************************/
  57.  
  58. #ifdef __ZTC__
  59. #ifdef __INLINE_8087
  60. #undef __INLINE_8087
  61. #endif
  62. #endif /*__ZTC__*/
  63.  
  64.  
  65. /****************************************************************************/
  66. /*  INCLUDES                                                                */
  67. /****************************************************************************/
  68.  
  69. #include <stdio.h>
  70. #include <string.h>
  71. #include <math.h>
  72. #include "adslib.h"
  73. #include "ol_errno.h"
  74. #include "util.h"
  75. #include "saget.h"
  76.  
  77.  
  78. /****************************************************************************/
  79. /*  DEFINES                                                                 */
  80. /****************************************************************************/
  81.  
  82. #define MAX_STR_LEN   501             /* Max string length            */
  83. #define MAX_UCS_LEVEL   5             /* Maximum level of UCS nesting */
  84.  
  85.  
  86. /****************************************************************************/
  87. /*  GLOBAL VARIABLES                                                        */
  88. /****************************************************************************/
  89.  
  90. int lisp_input = FALSE;               /* Input from AutoLISP list of resbufs*/
  91. int lisp_error = FALSE;               /* Error occured during AutoLISP input*/
  92.  
  93. struct resbuf *current_rb = NULL;     /* Next resbuf to read from AutoLISP  */
  94.  
  95. int sa_get_returned_RTCAN = FALSE;    /* Some sa_getxxx() returned RTCAN    */
  96.  
  97. ads_name implied_selset;                /* The implied selection set name   */
  98. int      implied_selset_exists = FALSE; /* The implied selection set exists */
  99.  
  100. /* The following global array of selection set names keeps the selection
  101.    sets which were read by sa_ssget() function. no_of_ssget_ss keeps the
  102.    number of selection sets read */
  103.  
  104. ads_name ssget_ss[20];                /* Array of selsets from sa_ssget() */
  105. int      no_of_ssget_ss = 0;          /* Number of selsets read           */
  106.  
  107.  
  108. /****************************************************************************/
  109. /*  STATIC VARIABLES                                                        */
  110. /****************************************************************************/
  111.  
  112. static struct igbuff
  113. {
  114.     int  val;
  115.     char kwl[MAX_STR_LEN];
  116.     char kw[MAX_STR_LEN];
  117.     int  cplast;
  118. } initget_buffer = {0, /* NT */"", /* NT */"", FALSE};
  119.  
  120. static struct
  121. {
  122.     ads_point p1, p2;
  123. } last_axis = {{ 0.0, 0.0, 0.0 },
  124.                { 0.0, 0.0, 0.0 }};
  125.  
  126. static struct
  127. {
  128.     ads_point p1, p2, p3;
  129. } last_plane = {{ 0.0, 0.0, 0.0 },
  130.                 { 0.0, 0.0, 0.0 },
  131.                 { 0.0, 0.0, 0.0 }};
  132.  
  133. static int           setcp_level = 0;     /* Level of SetCP nesting      */
  134. static int           ucs_level   = 0;     /* Level of UCS nesting        */
  135. static int           cp_used     = FALSE; /* CP used in last sa_getxxx() */
  136. static struct resbuf ucsicon;             /* Save area for UCSICON       */
  137.  
  138.  
  139. /****************************************************************************/
  140. /*  STATIC FUNCTIONSS                                                       */
  141. /****************************************************************************/
  142.  
  143. static int  invoke_calculator          _((int required_expr_type,
  144.                                           ads_point result));
  145. static void str_toupper                _((char *str));
  146. static void check_if_string_is_keyword _((char *word, char *kw));
  147. static int  is_null_argument           _((int *success));
  148. static int  get_from_ads               _((int func, ads_point pt,
  149.                                           char *prompt, ads_point res));
  150. static int  get_from_lisp              _((int func, ads_point res));
  151. static void convert_angle              _((int func, double *angle));
  152. static int  check_value                _((int func, double value));
  153. static int  match                      _((char *kw, char *pattern));
  154. static int  get_it                     _((int func, ads_point pt,
  155.                                           char *prompt, ads_point result));
  156.  
  157.  
  158. /****************************************************************************/
  159. /*.doc invoke_calculator(internal) */
  160. /*+
  161.   Invokes the GEOMCAL application and returns the value of the
  162.   evaluated expression in 'result'.
  163. -*/
  164. /****************************************************************************/
  165.  
  166.  
  167. static int
  168. /*FCN*/invoke_calculator(required_expr_type, result)
  169.  
  170.   int       required_expr_type;       /* RTREAL, RTSHORT or RT3DPOINT */
  171.   ads_point result;                   /* The returned value           */
  172. {
  173.     char          expr_str[MAX_STR_LEN];
  174.     struct resbuf *rb;
  175.     int           success;
  176.     struct resbuf *res = NULL;
  177.  
  178.     result[X] = result[Y] = result[Z] = 0.0;
  179.  
  180.     /* Load the "geomcal" application */
  181.  
  182.     success = ads_xload("geomcal");
  183.  
  184.     if (success != RTNORM) {
  185.         struct resbuf aerrno;
  186.         ads_getvar("ERRNO", &aerrno);
  187.         if (aerrno.resval.rint != OL_ELOADED) {
  188.             ads_printf("\n╕ⁿñJíu┤Xª≤¡p║ΓívÑ\134»α¿τ╝╞Ñó▒╤íC\n");
  189.             return(RTERROR);
  190.         }
  191.     }
  192.  
  193. Prompt:
  194.  
  195.     sa_initget(1, NULL);
  196.     success = sa_getstring(1, ">> ¡zÑy: ", expr_str);
  197.  
  198.     if ((success == RTERROR) || (success == RTCAN) || (success == RTREJ)) {
  199.         return(success);
  200.     } else if ((success != RTNORM) || (expr_str[0] == EOS)) {
  201.         if (!lisp_input) {
  202.             goto Prompt;
  203.         } else {
  204.             return(RTERROR);
  205.         }
  206.     }
  207.  
  208.     rb = ads_buildlist(RTSTR, /* NT */"CAL", RTSTR, expr_str, 0);
  209.  
  210.     success = ads_invoke(rb, &res);
  211.     ads_relrb(rb);
  212.  
  213.     if (success != RTNORM) {
  214.         ads_printf("\n░⌡ªµíu┤Xª≤¡p║ΓívÑ\134»αÑó▒╤íC\n");
  215.         return(RTERROR);
  216.     }
  217.  
  218.     if (res == NULL) {
  219.         if (!lisp_input) {
  220.             goto Prompt;
  221.         } else {
  222.             return(RTERROR);
  223.         }
  224.     }
  225.  
  226.     /* Calculator properly returned a list of resbufs,
  227.        let's check their type */
  228.  
  229.     switch (required_expr_type) {
  230.  
  231.     case RTREAL:
  232.         if ((res->rbnext != NULL) ||
  233.             (res->restype != RTREAL) && (res->restype != RTSHORT)) {
  234.  
  235.             ads_printf("\n¡zÑyÑ▓╢╖└╦─╢¼░íu╣Ω╝╞¡╚ívíC\n\n");
  236.             ads_relrb(res);
  237.             if (!lisp_input)
  238.                 goto Prompt;
  239.             else
  240.                 return(RTERROR);
  241.         }
  242.  
  243.         if (res->restype == RTREAL)
  244.             result[X] = res->resval.rreal;
  245.         else
  246.             result[X] = (double)res->resval.rint;
  247.         break;
  248.  
  249.     case RTSHORT:
  250.         if (res->restype != RTSHORT) {
  251.             ads_printf("\n¡zÑyÑ▓╢╖└╦─╢¼░íu╛π╝╞¡╚ívíC\n\n");
  252.             ads_relrb(res);
  253.             if (!lisp_input)
  254.                 goto Prompt;
  255.             else
  256.                 return(RTERROR);
  257.         }
  258.  
  259.         result[X] = (double)res->resval.rint;
  260.         break;
  261.  
  262.     case RT3DPOINT:
  263.         if (res->rbnext == NULL) {
  264. ads_printf("\n¡zÑyÑ▓╢╖└╦─╢¼░íu┬Ií■ªV╢qívíC\n\n");
  265.             ads_relrb(res);
  266.             if (!lisp_input)
  267.                 goto Prompt;
  268.             else
  269.                 return(RTERROR);
  270.         }
  271.  
  272.         result[X] = res->resval.rreal;
  273.         result[Y] = res->rbnext->resval.rreal;
  274.         result[Z] = res->rbnext->rbnext->resval.rreal;
  275.         break;
  276.  
  277.     default:
  278.         ads_relrb(res);
  279.         return(RTREJ);
  280.     } /*switch*/
  281.  
  282.     ads_relrb(res);
  283.     return(RTNORM);
  284. } /*invoke_calculator*/
  285.  
  286.  
  287. static void
  288. /*FCN*/str_toupper(str)
  289.  
  290.   char *str;
  291. {
  292.     while ((*str = ads_toupper(*str)) != 0)
  293.         str++;
  294. } /*str_toupper*/
  295.  
  296.  
  297. /****************************************************************************/
  298. /*.doc check_if_string_is_keyword(internal) */
  299. /*+
  300.   Checks whether the given string 'word' is one of the keywords from
  301.   initget_buffer.kwl. If yes, gives the keyword 'kw', otherwise
  302.   gives "".
  303. -*/
  304. /****************************************************************************/
  305.  
  306.  
  307. static void
  308. /*FCN*/check_if_string_is_keyword(word, kw)
  309.  
  310.   char word[];                        /* Input string                     */
  311.   char kw[];                          /* Output keyword or "" if no match */
  312. {
  313.     char kwl[MAX_STR_LEN];
  314.     char w[MAX_STR_LEN];
  315.     char whole_kw[MAX_STR_LEN], short_kw[MAX_STR_LEN];
  316.     char *ch, *space, *comma;
  317.     int  w_len, s_len;
  318.     int  word_underscored = FALSE;
  319.     char *underscore_pos;
  320.     int  count = 0;
  321.  
  322.     /* Initialize 'kw', make local copy of input 'word', strip off
  323.        the leading underscore, if present */
  324.  
  325.     kw[0] = EOS;
  326.  
  327.     if (word[0] == /* NT */'_') {
  328.         strcpy(w, word + 1);
  329.         word_underscored = TRUE;
  330.     } else {
  331.         strcpy(w, word);
  332.     }
  333.     str_toupper(w);
  334.  
  335.     if (word[0] == EOS)
  336.         return;
  337.  
  338.     strcpy(kwl, initget_buffer.kwl);
  339.  
  340.     underscore_pos = strstr(kwl, /* NT */" _");
  341.     if (underscore_pos != NULL) {
  342.         underscore_pos++;
  343.  
  344.         if (word_underscored) {
  345.             ch = underscore_pos + 1; /* Check only keywords following "_" */
  346.         } else {
  347.             ch = kwl;
  348.             *underscore_pos = EOS;   /* Check only keywords preceding "_" */
  349.         }
  350.     } else {
  351.         ch = kwl;
  352.     }
  353.  
  354.     /* Go through all the keywords in initget_buffer.kwl */
  355.  
  356.     for (;;) {
  357.  
  358.         /* Go to the beginning of the next kword */
  359.  
  360.         while (*ch == /* NT */' ') {
  361.             ch++;
  362.         }
  363.         if (*ch == EOS)
  364.             return;                   /*Not found*/
  365.  
  366.         /* Parse the keyword specification */
  367.  
  368.         count++;
  369.  
  370.         /* Find the position of the terminating space */
  371.  
  372.         space = strchr(ch, /* NT */' ');
  373.         if (space == NULL)
  374.             space = kwl + strlen(kwl);
  375.  
  376.         comma = strchr(ch, /* NT */',');
  377.         if ((comma != NULL) && (comma > space))
  378.             comma = NULL;
  379.  
  380.         /* Assign whole_kw and short_kw */
  381.  
  382.         if (comma == NULL) {
  383.             char *c = short_kw;
  384.  
  385.             w_len = space - ch;
  386.             strncpy(whole_kw, ch, w_len); whole_kw[w_len] = EOS;
  387.  
  388.             strcpy (short_kw, whole_kw);
  389.             while (*c != EOS) {
  390.                 if (ads_islower(*c)) {
  391.                     if (c != short_kw)  /*Not the first character*/
  392.                         *c = EOS;
  393.                     break;
  394.                 }
  395.                 c++;
  396.             } /*while*/
  397.         } else {
  398.             w_len = comma - ch;
  399.             s_len = space - (comma+1);
  400.  
  401.             strncpy(whole_kw, ch,      w_len); whole_kw[w_len] = EOS;
  402.             strncpy(short_kw, comma+1, s_len); short_kw[s_len] = EOS;
  403.         } /*else*/
  404.  
  405.         str_toupper(whole_kw);
  406.         str_toupper(short_kw);
  407.  
  408.         /*
  409.           If 'w'        is prefix of 'whole_kw' and
  410.              'short_kw' is prefix of 'w'
  411.              then 'w' is a keyword.
  412.         */
  413.  
  414.         if ((strstr(whole_kw, w       ) == whole_kw) &&
  415.             (strstr(w,        short_kw) == w       ))   {
  416.  
  417.             int len;
  418.  
  419.             if (comma != NULL)
  420.                 len = comma - ch;
  421.             else
  422.                 len = space - ch;
  423.  
  424.             strncpy(kw, ch, len); kw[len] = EOS;
  425.             break;                    /*Found*/
  426.         }
  427.  
  428.         /* Go to the space terminating the checked keyword */
  429.  
  430.         ch = space;
  431.     } /*forever*/
  432.  
  433.     /* The keyword was found. But if the given word was underscored
  434.        and the list of keywords contains both the orignal and language
  435.        dependent keywords, then instead of returning the keyword found
  436.        we return its language dependent equivalent */
  437.  
  438.     if (word_underscored && (underscore_pos != NULL)) {
  439.         char *tok;
  440.         int  i;
  441.  
  442.         /* Go to the count's token in the list of keywords */
  443.  
  444.         tok = strtok(kwl, " ");
  445.         for (i = 0; i < count - 1; i++) {
  446.             tok = strtok(NULL, " ");
  447.         }
  448.         if (tok != NULL) {
  449.             strcpy(kw, tok);
  450.         } else {
  451.             kw[0] = EOS;
  452.         }
  453.     }
  454.  
  455. } /*check_if_string_is_keyword*/
  456.  
  457.  
  458. /****************************************************************************/
  459. /*.doc is_null_argument(internal)*/
  460. /*+
  461.   Checks whether the next argument in the AutoLISP's list of resbufs
  462.   is null, that is NIL or "".
  463. -*/
  464. /****************************************************************************/
  465.  
  466.  
  467. static int
  468. /*FCN*/is_null_argument(success)
  469.  
  470.   int *success;
  471. {
  472.     if (current_rb == NULL) {
  473.         if (initget_buffer.val & RSG_NONULL) {
  474.             ads_printf("\n┐∙╗~:íuñ▐╝╞ív╣Lñ╓íC\n\n");
  475.             *success = RTERROR;
  476.         } else {
  477.             *success = RTNONE;
  478.         }
  479.         return(TRUE);
  480.     }
  481.  
  482.     if ((current_rb->restype == RTNIL) ||
  483.         (current_rb->restype == RTSTR) &&
  484.         (current_rb->resval.rstring[0] == EOS)) {
  485.         if (initget_buffer.val & RSG_NONULL) {
  486.             ads_printf("\n┐∙╗~: ñú▒╡¿ⁿíuNull ñ▐╝╞ívíC\n\n");
  487.             *success = RTERROR;
  488.         } else {
  489.             *success = RTNONE;
  490.         }
  491.         return(TRUE);
  492.     }
  493.     return(FALSE);
  494. } /*is_null_argument*/
  495.  
  496.  
  497. /****************************************************************************/
  498. /*.doc get_from_ads(internal)*/
  499. /*+
  500.   Function calls one of the standard ads_getxxx() functions.
  501. -*/
  502. /****************************************************************************/
  503.  
  504.  
  505. static int
  506. /*FCN*/get_from_ads(func, pt, prompt, res)
  507.  
  508.   int        func;                    /*'I' == int, 'P' == point, etc. */
  509.   ads_point  pt;                      /* Reference point               */
  510.   char       *prompt;
  511.   ads_point  res;
  512. {
  513.     int success;
  514.  
  515.     switch (func) {
  516.  
  517.     case /* NT */'I': {
  518.             int i;
  519.             success = ads_getint(prompt, &i);     /*int*/
  520.             res[X] = (double) i;
  521.             break;
  522.         }
  523.     case /* NT */'R':
  524.         success = ads_getreal(prompt, res);       /*double*/
  525.         break;
  526.     case /* NT */'A':
  527.         success = ads_getangle(pt, prompt, res);  /*double*/
  528.         break;
  529.     case /* NT */'C':
  530.         success = ads_getcorner(pt, prompt, res); /*point*/
  531.         break;
  532.     case /* NT */'D':
  533.         success = ads_getdist(pt, prompt, res);   /*double*/
  534.         break;
  535.     case /* NT */'O':
  536.         success = ads_getorient(pt, prompt, res); /*double*/
  537.         break;
  538.     case /* NT */'P':
  539.         success = ads_getpoint(pt, prompt, res);  /*point*/
  540.         break;
  541.     default:
  542.         success = RTREJ;
  543.         break;
  544.     } /*switch*/
  545.  
  546.     return(success);
  547. } /*get_from_ads*/
  548.  
  549.  
  550. /****************************************************************************/
  551. /*.doc get_from_lisp(internal)*/
  552. /*+
  553.   Function gets one argument from the AutoLISP's list of result buffers.
  554. -*/
  555. /****************************************************************************/
  556.  
  557.  
  558. static int
  559. /*FCN*/get_from_lisp(func, res)
  560.  
  561.   int       func;
  562.   ads_point res;
  563. {
  564.     int  type;
  565.     int  success;
  566.     char kw[MAX_STR_LEN];
  567.  
  568.     if (lisp_error)
  569.         return(RTERROR);
  570.  
  571.     if (is_null_argument(&success))
  572.         goto End;
  573.  
  574.     type = current_rb->restype;
  575.  
  576.     /* Is it a keyword? */
  577.  
  578.     if (type == RTSTR) {
  579.  
  580.         check_if_string_is_keyword(current_rb->resval.rstring, kw);
  581.  
  582.         if (kw[0] != EOS) {
  583.             strcpy(initget_buffer.kw, kw);
  584.             success = RTKWORD;
  585.  
  586.         } else if (initget_buffer.val & RSG_OTHER) {
  587.             strcpy(initget_buffer.kw, current_rb->resval.rstring);
  588.             str_toupper(initget_buffer.kw);
  589.             success = RTKWORD;
  590.  
  591.         } else {
  592.             ads_printf("\n┐∙╗~: ├÷┴Σªríu%sívñúªX▓zíC\n\n",
  593.                        current_rb->resval.rstring);
  594.             success = RTERROR;
  595.         }
  596.         goto End;
  597.     } /*if*/
  598.  
  599.     /* Switch depending on the type of the sa_getxxx() function */
  600.  
  601.     switch (func) {
  602.  
  603.     case /* NT */'I':                 /*Integer*/
  604.         switch (type) {
  605.         case RTSHORT:
  606.             res[X] = (double)current_rb->resval.rint;
  607.             success = RTNORM;
  608.             break;
  609.         default:
  610.             ads_printf("\n┐∙╗~:íu░╤╝╞ív└│¼░íu╛π╝╞ívíC\n\n");
  611.             success = RTERROR;
  612.             goto End;
  613.         } /*switch*/
  614.         break;
  615.  
  616.     case /* NT */'R':                 /*Real*/
  617.     case /* NT */'D':
  618.     case /* NT */'A':
  619.     case /* NT */'O':
  620.         switch (type) {
  621.         case RTSHORT:
  622.             res[X] = (double)current_rb->resval.rint;
  623.             success = RTNORM;
  624.             break;
  625.         case RTLONG:
  626.             res[X] = (double)current_rb->resval.rlong;
  627.             success = RTNORM;
  628.             break;
  629.         case RTREAL:
  630.         case RTANG:
  631.         case RTORINT:
  632.             res[X] = current_rb->resval.rreal;
  633.             success = RTNORM;
  634.             break;
  635.         default:
  636.             ads_printf("\n┐∙╗~:íu░╤╝╞ív└│¼░íu╣Ω╝╞ívíC\n\n");
  637.             success = RTERROR;
  638.             goto End;
  639.         } /*switch*/
  640.         break;
  641.  
  642.     case /* NT */'P':
  643.     case /* NT */'C':
  644.         switch (type) {
  645.         case RTPOINT:
  646.         case RT3DPOINT:
  647.             CPY_PNT(res, current_rb->resval.rpoint);
  648.             success = RTNORM;
  649.             break;
  650.         default:
  651.             ads_printf("\n┐∙╗~:íu░╤╝╞ív└│¼░íu┬Ií■ªV╢qívíC\n\n");
  652.             success = RTERROR;
  653.             goto End;
  654.         } /*switch*/
  655.         func = /* NT */'P';
  656.         break;
  657.  
  658.     default:
  659.         success = RTREJ;
  660.         goto End;
  661.     } /*switch*/
  662.  
  663.     if (!check_value(func, res[X])) {
  664.         success = RTERROR;
  665.         goto End;
  666.     }
  667.  
  668.     if ((func == /* NT */'A') || (func == /* NT */'O')) {
  669.         convert_angle(func, &res[X]);
  670.     }
  671.  
  672. End:
  673.     if (current_rb != NULL)
  674.         current_rb = current_rb->rbnext;
  675.     lisp_error = ((success != RTNORM)  && (success != RTNONE) &&
  676.                   (success != RTKWORD));
  677.     return(success);
  678. } /*get_from_lisp*/
  679.  
  680.  
  681. /****************************************************************************/
  682. /*.doc convert_angle(internal)*/
  683. /*+
  684.   Converts the given angle from the current units and orientation to ccw
  685.   measured radians. Takes into account the values of AutoCAD variables
  686.   ANGDIR, AUNITS and ANGBASE.
  687. -*/
  688. /****************************************************************************/
  689.  
  690.  
  691. static void
  692. /*FCN*/convert_angle(func, angle)
  693.  
  694.   int    func;
  695.   double *angle;
  696. {
  697.     struct resbuf angdir, aunits;
  698.     double ang = *angle;
  699.  
  700.     ads_getvar("ANGDIR",  &angdir);
  701.     ads_getvar("AUNITS",  &aunits);
  702.  
  703.     /* Orient the angle counterclockwise */
  704.  
  705.     if (angdir.resval.rint == 1) {
  706.         ang = -ang;
  707.     }
  708.  
  709.     /* Convert from the current units to radians */
  710.  
  711.     switch (aunits.resval.rint) {
  712.     case 2:
  713.         ang *= (0.9 * DEGRAD);
  714.         break;
  715.     case 3:
  716.         /* Already in radians */
  717.         break;
  718.     default:
  719.         ang *= DEGRAD;
  720.         break;
  721.     } /*switch*/
  722.  
  723.     /* If the function is sa_getorient(), add ANGBASE angle */
  724.  
  725.     if (func == /* NT */'O') {
  726.         struct resbuf angbase;
  727.         ads_getvar("ANGBASE", &angbase);
  728.  
  729.         ang += angbase.resval.rreal;
  730.     }
  731.  
  732.     sa_normalize_angle(&ang);
  733.     *angle = ang;
  734. } /*convert_angle*/
  735.  
  736.  
  737. /****************************************************************************/
  738. /*.doc check_value(internal)*/
  739. /*+
  740.   Check the given real value whether it satisfies the initget bits
  741.   RSG_NOZERO and RSG_NONEG. Returns TRUE if the value is OK, FALSE otherwise.
  742. -*/
  743. /****************************************************************************/
  744.  
  745.  
  746. static int
  747. /*FCN*/check_value(func, value)
  748.  
  749.   int    func;
  750.   double value;
  751. {
  752.     /* For reals and integers check flags RSG_NOZERO & RSG_NONEG */
  753.  
  754.     if ((func == /* NT */'I') ||
  755.         (func == /* NT */'R') || (func == /* NT */'D') ||
  756.         (func == /* NT */'A') || (func == /* NT */'O')) {
  757.  
  758.         if ((initget_buffer.val & RSG_NOZERO) && (value == 0.0)) {
  759.             ads_printf("\n┐∙╗~: ╝╞¡╚ñúÑi¼░íu0ívíC\n\n");
  760.             return(FALSE);
  761.         }
  762.         if ((initget_buffer.val & RSG_NONEG) && (value < 0.0)) {
  763.             ads_printf("\n┐∙╗~: ╝╞Ñ╪ñúÑi¼░íu¡t¡╚ívíC\n\n");
  764.             return(FALSE);
  765.         }
  766.     }
  767.     return(TRUE);
  768. } /*check_value*/
  769.  
  770.  
  771. /****************************************************************************/
  772. /*.doc match(internal)*/
  773. /*+
  774.   Check whether
  775.                 kw == pattern     or
  776.                 kw == 'pattern    or
  777.                 kw == (pattern)   or
  778.                 kw == (C:pattern)
  779.  
  780.   This awkward code is necessary as the user input 'XXX is converted to
  781.   either (XXX) or (C:XXX) or left unchanged as 'XXX.
  782. -*/
  783. /****************************************************************************/
  784.  
  785.  
  786. static int
  787. /*FCN*/match(kw, pattern)
  788.  
  789.   char *kw;
  790.   char *pattern;
  791. {
  792.     char pat[MAX_STR_LEN];
  793.  
  794.     if (strcmp(kw, pattern) == 0)
  795.         return(TRUE);
  796.  
  797.     if ((kw[0] != /* NT */'(') && (kw[0] != /*ASCII character ' */ 39))
  798.         return(FALSE);
  799.  
  800.     if ((kw[0] == /*ASCII character ' */ 39) &&
  801.         (strcmp(kw + 1, pattern) == 0))
  802.         return(TRUE);
  803.  
  804.     pat[0] = EOS;
  805.     strcat(pat, /* NT */"(C:");
  806.     strcat(pat, pattern);
  807.     strcat(pat, /* NT */")");
  808.  
  809.     if (strcmp(kw, pat) == 0)
  810.         return(TRUE);
  811.  
  812.     pat[0] = EOS;
  813.     strcat(pat, /* NT */"(");
  814.     strcat(pat, pattern);
  815.     strcat(pat, /* NT */")");
  816.  
  817.     if (strcmp(kw, pat) == 0)
  818.         return(TRUE);
  819.  
  820.     return(FALSE);
  821. } /*match*/
  822.  
  823.  
  824. /****************************************************************************/
  825. /*.doc get_it(internal)*/
  826. /*+
  827.     General sa_getxxx() routine. Is implemented to avoid writing similar
  828.     code for individual sa_getpoint(), sa_getangle(), sa_getdist() etc.
  829. -*/
  830. /****************************************************************************/
  831.  
  832.  
  833. static int
  834. /*FCN*/get_it(func, pt, prompt, result)
  835.  
  836.   int        func;                    /* 'P' == getpoint, 'D' == getdist... */
  837.   ads_point  pt;                      /* Reference point                    */
  838.   char       *prompt;                 /* Prompt (optional)                  */
  839.   ads_point  result;                  /* Returned result                    */
  840. {
  841.     char          kw[MAX_STR_LEN];
  842.     int           success;
  843.     char          cp_option[10];
  844.     struct igbuff initget_save;
  845.     struct resbuf ucsicon_save;
  846.     int           ucsicon_saved = FALSE;
  847.     ads_point     res;
  848.     ads_point     ref_pt;
  849.     ads_point     ref_pt_wcs;
  850.     double        *ref_pt_ptr;
  851.  
  852.     /* Save the reference point pt and initget_buffer */
  853.  
  854.     if (pt != NULL) {
  855.         CPY_PNT(ref_pt, pt);
  856.         sa_u2w(ref_pt, ref_pt_wcs);
  857.         ref_pt_ptr = ref_pt;
  858.     } else {
  859.         ref_pt_ptr = NULL;
  860.     }
  861.  
  862.     initget_save  = initget_buffer;
  863.     cp_used = FALSE;
  864.  
  865.     /* If sa_init_cplast() was used, go directly to CPL (Last) option */
  866.  
  867.     if (initget_save.cplast) {
  868.         strcpy(kw, "CPL");
  869.         goto Check_kword;
  870.     }
  871.  
  872. Prompt:
  873.  
  874.    /* Get the input from the user or from AutoLISP. Notice that
  875.       we are explicitly setting the RSG_OTHER initget bit. This is
  876.       necessary for supporting 'CAL, 'CP etc, which are returned
  877.       as arbitrary keyboard input, not as keywords.
  878.    */
  879.  
  880.     kw[0] = EOS;
  881.     sa_initget(initget_save.val | RSG_OTHER, initget_save.kwl);
  882.  
  883.     if (lisp_input) {
  884.         success = get_from_lisp(func, res);
  885.     } else {
  886.         success = get_from_ads(func, ref_pt_ptr, prompt, res);
  887.     }
  888.  
  889.     if (success != RTKWORD)
  890.         goto End;
  891.  
  892.     if (lisp_input) {
  893.         sa_getinput(kw);
  894.     } else {
  895.         ads_getinput(kw);
  896.     }
  897.  
  898. Check_kword:
  899.  
  900.    /* Check whether the string 'kw' is one of the reserved keywords
  901.       such as 'CAL, 'CP etc. Notice that these reserved keywords are
  902.       returned as arbitrary keyboard input strings.
  903.    */
  904.  
  905.     cp_option[0] = EOS;
  906.  
  907.     if (match(kw, "CAL")) {
  908.         strcpy(kw, "CAL");
  909.  
  910.     } else if (match(kw, "CP")) {
  911.         strcpy(kw, "CP");
  912.  
  913.     } else if (match(kw, "CPE")) {
  914.         strcpy(kw, "CP");
  915.         strcpy(cp_option, "Entity");
  916.  
  917.     } else if (match(kw, "CPV")) {
  918.         strcpy(kw, "CP");
  919.         strcpy(cp_option, "View");
  920.  
  921.     } else if (match(kw, "CPZ")) {
  922.         strcpy(kw, "CP");
  923.         strcpy(cp_option, "Zaxis");
  924.  
  925.     } else if (match(kw, "CPXY")) {
  926.         strcpy(kw, "CP");
  927.         strcpy(cp_option, "XY");
  928.  
  929.     } else if (match(kw, "CPYZ")) {
  930.         strcpy(kw, "CP");
  931.         strcpy(cp_option, "YZ");
  932.  
  933.     } else if (match(kw, "CPZX")) {
  934.         strcpy(kw, "CP");
  935.         strcpy(cp_option, "ZX");
  936.  
  937.     } else if (match(kw, "CPL")) {
  938.         strcpy(kw, "CP");
  939.         strcpy(cp_option, "Last");
  940.  
  941.     } else if (match(kw, "CP3")) {
  942.         strcpy(kw, "CP");
  943.         strcpy(cp_option, "3points");
  944.  
  945.     } else if ((initget_save.val & RSG_OTHER) == 0) {
  946.  
  947.         /* As we forecfully added the RSG_OTHER bit to ads_initget(), this
  948.            means that all wrong input will be returned as arbitrary
  949.            keyboard input string. But if the user himself didn't set the
  950.            RSG_OTHER flag, we want to print an error if the string is
  951.            not any of the legal keywords.
  952.         */
  953.  
  954.         char tmp[MAX_STR_LEN];
  955.         check_if_string_is_keyword(kw, tmp);
  956.  
  957.         if (tmp[0] == EOS) {
  958.             ads_printf("\n╡L«─¬║íu┐ΘñJívíC\n");
  959.  
  960.             if (!lisp_input) {
  961.                 goto Prompt;
  962.             } else {
  963.                 goto End;
  964.             }
  965.         }
  966.     }
  967.  
  968.     if (strcmp(kw, "CP") == 0) {
  969.  
  970.         ads_point     origin, xaxis, yaxis;
  971.         int           i;
  972.         struct resbuf ucsi;
  973.  
  974.         if (ucs_level >= MAX_UCS_LEVEL) {
  975.             ads_printf("\nCPíu▒_▓╒╝h╢Ñív╣L▓`íC\n\n");
  976.             if (!lisp_input)
  977.                 goto Prompt;
  978.             else {
  979.                 success = RTERROR;
  980.                 goto End;
  981.             }
  982.         }
  983.  
  984.         if (!ucsicon_saved) {
  985.             ads_getvar("UCSICON", &ucsicon_save);
  986.             ucsicon_saved = TRUE;
  987.         }
  988.  
  989.         /* Prompt for the construction plane */
  990.  
  991.         success = sa_getplane("\nCP", cp_option, origin, xaxis, yaxis);
  992.         if (!lisp_input && (success == RTCAN)) {
  993.             goto Prompt;
  994.         } else if (success != RTNORM)
  995.             goto End;
  996.  
  997.         /* Align UCS with the construction plane */
  998.  
  999.         sa_save_acad_vars();
  1000.  
  1001.         success = ads_command(RTSTR, /* NT */"_.UCS", RTSTR, /* NT */"_3",
  1002.                               RT3DPOINT, origin,
  1003.                               RT3DPOINT, xaxis,
  1004.                               RT3DPOINT, yaxis, 0);
  1005.         sa_restore_acad_vars();
  1006.  
  1007.         if (success != RTNORM) {
  1008.             ads_printf("\n¼░íu½╪║cÑ¡¡▒ív│]⌐w UCS Ñó▒╤\n\n");
  1009.             success = RTERROR;
  1010.             goto End;
  1011.         }
  1012.         ucs_level++;
  1013.  
  1014.         /* Transform 'ref_pt_wcs' from WCS to CP */
  1015.  
  1016.         if (ref_pt_ptr != NULL)
  1017.             sa_w2u(ref_pt_wcs, ref_pt);
  1018.  
  1019.         /* Display ucs icon at the origin of the construction plane */
  1020.  
  1021.         ucsi.restype     = RTSHORT;
  1022.         ucsi.resval.rint = 3;
  1023.         ads_setvar("UCSICON",&ucsi);
  1024.  
  1025.         /* Exclude keyword "Baseplane" after CP was used */
  1026.  
  1027.         if (strncmp(initget_save.kwl, "Baseplane", 9) == 0) {
  1028.             for (i = 0; i < 9; i++)
  1029.                 initget_save.kwl[i] = /* NT */' ';
  1030.         }
  1031.  
  1032.         /* Get a value relative to the construction plane */
  1033.         /* Notice the recursiive call to get_it()         */
  1034.  
  1035.         sa_initget(initget_save.val, initget_save.kwl);
  1036.         success = get_it(func, ref_pt_ptr, prompt, res);
  1037.  
  1038.         if ((success == RTKWORD) || (success == RTSTR))
  1039.             sa_getinput(kw);
  1040.  
  1041.         /* Transform result 'res' CP->UCS if it is a point */
  1042.  
  1043.         if (((func == /* NT */'C') || (func == /* NT */'P'))
  1044.             && (success == RTNORM)) {
  1045.             sa_u2w(res, res);
  1046.         }
  1047.  
  1048.         /* Return UCS back, hide UCSICON to avoid jumping of the icon */
  1049.  
  1050.         ucsi.restype     = RTSHORT;
  1051.         ucsi.resval.rint = 0;
  1052.         ads_setvar("UCSICON", &ucsi);
  1053.  
  1054.         sa_cmdecho_off();
  1055.         ads_command(RTSTR, /* NT */"_.UCS", RTSTR, /* NT */"_PREV", 0);
  1056.         sa_cmdecho_back();
  1057.         ucs_level--;
  1058.  
  1059.         if (((func == /* NT */'C') || (func == /* NT */'P'))
  1060.             && (success == RTNORM)) {
  1061.             sa_w2u(res, res);
  1062.         }
  1063.  
  1064.         cp_used = TRUE;
  1065.  
  1066.     } else if (strcmp(kw, "Baseplane") == 0) {
  1067.  
  1068.         if (ucs_level >= MAX_UCS_LEVEL) {
  1069.             ads_printf("\n░≥╖╟¡▒íu▒_▓╒╝h╢Ñív╣L▓`íC\n\n");
  1070.             if (!lisp_input)
  1071.                 goto Prompt;
  1072.             else {
  1073.                 success = RTERROR;
  1074.                 goto End;
  1075.             }
  1076.         }
  1077.  
  1078.         if (!ucsicon_saved) {
  1079.             ads_getvar("UCSICON", &ucsicon_save);
  1080.             ucsicon_saved = TRUE;
  1081.         }
  1082.  
  1083.         success = sa_set_cp("\n░≥╖╟¡▒");
  1084.         cp_used = FALSE;
  1085.  
  1086.         if (!lisp_input && (success == RTCAN)) {
  1087.             goto Prompt;
  1088.         } else if (success != RTNORM)
  1089.             goto End;
  1090.  
  1091.         ads_getvar("UCSICON", &ucsicon_save);
  1092.         if (ref_pt_ptr != NULL)
  1093.             sa_w2u(ref_pt_wcs, ref_pt);
  1094.         goto Prompt;
  1095.  
  1096.     } else if (strcmp(kw, /* NT */"CAL") == 0) {
  1097.  
  1098.         int required_expr_type;
  1099.  
  1100.         switch (func) {
  1101.  
  1102.         case /* NT */'P':
  1103.         case /* NT */'C':
  1104.             required_expr_type = RT3DPOINT;
  1105.             break;
  1106.         case /* NT */'D':
  1107.         case /* NT */'A':
  1108.         case /* NT */'O':
  1109.         case /* NT */'R':
  1110.             required_expr_type = RTREAL;
  1111.             break;
  1112.         case /* NT */'I':
  1113.             required_expr_type = RTSHORT;
  1114.             break;
  1115.         default:
  1116.             success = RTERROR;
  1117.             goto End;
  1118.         } /*switch*/
  1119.  
  1120.         success = invoke_calculator(required_expr_type, res);
  1121.  
  1122.         if (!lisp_input && (success == RTCAN))
  1123.             goto Prompt;
  1124.         else if (success != RTNORM)
  1125.             goto End;
  1126.  
  1127.         if (!check_value(func, res[X])) {
  1128.             if (!lisp_input) {
  1129.                 goto Prompt;
  1130.             } else {
  1131.                 success = RTERROR;
  1132.                 goto End;
  1133.             }
  1134.         }
  1135.  
  1136.         if ((func == /* NT */'A') || (func == /* NT */'O')) {
  1137.             convert_angle(func, &res[X]);
  1138.         }
  1139.  
  1140.     } else {
  1141.         success = RTKWORD;
  1142.     }
  1143.  
  1144. End:
  1145.     if (success == RTNORM)
  1146.         CPY_PNT(result, res);
  1147.  
  1148.     sa_initget(0, NULL);
  1149.     strcpy(initget_buffer.kw, kw);
  1150.  
  1151.     if (ucsicon_saved) {
  1152.         ads_setvar("UCSICON", &ucsicon_save);
  1153.     }
  1154.  
  1155.     sa_get_returned_RTCAN = (success == RTCAN);
  1156.  
  1157.     return(success);
  1158. } /*get_it*/
  1159.  
  1160.  
  1161. /****************************************************************************/
  1162. /*.doc sa_init_input(external)*/
  1163. /*+
  1164.   This function must be called before each ADS command. It initializes the
  1165.   system and reads the arguments (list of result buffers) which AutoLISP
  1166.   passes to the AME command being activated. It also reads the implied
  1167.   selection set and stores it in global variable implied_selset. The global
  1168.   integer variable implied_selset_exists is set to TRUE if there is an
  1169.   implied selection set.
  1170.  
  1171.   It is convenient to call sa_init_input() from main(), before processing the
  1172.   RQSUBR request from ads_link().
  1173.  
  1174.   The 'input_source' argument is used to determine whether the input of
  1175.   sa_getxxx() functions will go from the keyboard or from AutoLISP's list
  1176.   of result buffers.
  1177.  
  1178.   0 ... input from AutoLISP if a resbuf list present, otherwise from keyboard.
  1179.   1 ... input from AutoLISP even if no resbuf list present
  1180.   2 ... input from keyboard even if a resbuf list present.
  1181.  
  1182.   Function always returns RTNORM.
  1183.  
  1184.   Note:
  1185.  
  1186.   Don't forget to explicitly free the stored and unused implied selection
  1187.   when you are leaving the ADS application. The number of currently open
  1188.   selection set names is limited. See the code 30 lines below how to do this.
  1189. -*/
  1190. /****************************************************************************/
  1191.  
  1192.  
  1193. int
  1194. /*FCN*/sa_init_input(input_source)
  1195.  
  1196.   int input_source;
  1197. {
  1198.     int success;
  1199.  
  1200.     switch (input_source) {
  1201.     case 0:
  1202.         current_rb = ads_getargs();
  1203.         lisp_input = (current_rb != NULL);
  1204.         break;
  1205.     case 1:
  1206.         current_rb = ads_getargs();
  1207.         lisp_input = TRUE;
  1208.         break;
  1209.     case 2:
  1210.         current_rb = NULL;
  1211.         lisp_input = FALSE;
  1212.         break;
  1213.     default:
  1214.         current_rb = NULL;
  1215.         lisp_input = FALSE;
  1216.         break;
  1217.     } /*switch*/
  1218.  
  1219.     /************************************************************************
  1220.       Free the stored and unused implied selection set. You should
  1221.       explicitly free the stored implied selection set when you are leaving
  1222.       the ADS application or any time when sa_init_input() is not called to
  1223.       free it for you.
  1224.      ************************************************************************/
  1225.  
  1226.     if (implied_selset_exists) {
  1227.         ads_ssfree(implied_selset);
  1228.         implied_selset_exists = FALSE;
  1229.     }
  1230.  
  1231.     /* Get the implied selection set, if there is any */
  1232.  
  1233.     success = ads_ssget(/* NT */"_I", NULL, NULL, NULL, implied_selset);
  1234.     implied_selset_exists = (success == RTNORM);
  1235.  
  1236.     if (lisp_input) {
  1237.         ads_retnil();
  1238.     } else {
  1239.         ads_retvoid();
  1240.     }
  1241.  
  1242.     lisp_error            = FALSE;
  1243.     sa_get_returned_RTCAN = FALSE;
  1244.     no_of_ssget_ss        = 0;
  1245.  
  1246.     return(RTNORM);
  1247. } /*sa_init_input*/
  1248.  
  1249.  
  1250. /****************************************************************************/
  1251. /*.doc sa_initget(external)*/
  1252. /*+
  1253.   Analogy to ads_initget() but must be used with sa_getxxx() functions.
  1254. -*/
  1255. /****************************************************************************/
  1256.  
  1257.  
  1258. int
  1259. /*FCN*/sa_initget(val, kwl)
  1260.  
  1261.   int  val;
  1262.   char *kwl;
  1263. {
  1264.     int success;
  1265.  
  1266.     success = ads_initget(val, kwl);
  1267.     if (success != RTNORM)
  1268.         return(success);
  1269.  
  1270.     initget_buffer.val = val;
  1271.     if (kwl != NULL) {
  1272.         strcpy(initget_buffer.kwl, kwl);
  1273.     } else {
  1274.         initget_buffer.kwl[0] = EOS;
  1275.     }
  1276.  
  1277.     initget_buffer.kw[0]  = EOS;
  1278.     initget_buffer.cplast = FALSE;
  1279.  
  1280.     return(RTNORM);
  1281. } /*sa_initget*/
  1282.  
  1283.  
  1284. /****************************************************************************/
  1285. /*.doc sa_init_cplast(external)*/
  1286. /*+
  1287.   The purpose of this function is similar to sa_initget(), that is modifying
  1288.   the behavior of the next sa_getxxx() call. It sets that the next sa_getxxx()
  1289.   function will automatically jump to the CP used in the last sa_getxxx()
  1290.   function. If no CP was used in the last sa_getxxx() then nothing happens.
  1291.  
  1292.   This function must be called AFTER sa_initget() and before the sa_getxxx()
  1293.   function.
  1294.  
  1295.   Function always returns RTNORM.
  1296. -*/
  1297. /****************************************************************************/
  1298.  
  1299.  
  1300. int
  1301. /*FCN*/sa_init_cplast()
  1302. {
  1303.     initget_buffer.cplast = (cp_used);
  1304.     return(RTNORM);
  1305. } /*sa_init_cplast*/
  1306.  
  1307.  
  1308. /****************************************************************************/
  1309. /*.doc sa_getinput(external)*/
  1310. /*+
  1311.   Analogy to ads_getinput() but must be used with sa_getxxx() functions.
  1312. -*/
  1313. /****************************************************************************/
  1314.  
  1315.  
  1316. int
  1317. /*FCN*/sa_getinput(str)
  1318.  
  1319.   char *str;
  1320. {
  1321.     if (initget_buffer.kw[0] == EOS)
  1322.         return(RTERROR);
  1323.  
  1324.     strcpy(str, initget_buffer.kw);
  1325.     initget_buffer.kw[0] = EOS;
  1326.     return(RTNORM);
  1327. } /*sa_getinput*/
  1328.  
  1329.  
  1330. /****************************************************************************/
  1331. /*.doc sa_getpoint(external)*/
  1332. /*+
  1333.   Enhanced ads_getpoint() function which supports keyboard/AutoLISP input
  1334.   redirection and 'CAL, 'CP and Baseplane options.
  1335. -*/
  1336. /****************************************************************************/
  1337.  
  1338.  
  1339. int
  1340. /*FCN*/sa_getpoint(pt, prompt, result)
  1341.  
  1342.   ads_point pt;
  1343.   char      *prompt;
  1344.   ads_point result;
  1345. {
  1346.     int       success;
  1347.     ads_point p;
  1348.  
  1349.     success = get_it(/* NT */'P', pt, prompt, p);
  1350.     if (success == RTNORM)
  1351.         CPY_PNT(result, p);
  1352.     return(success);
  1353. } /*sa_getpoint*/
  1354.  
  1355.  
  1356. /****************************************************************************/
  1357. /*.doc sa_getcorner(external)*/
  1358. /*+
  1359.   Enhanced ads_getcorner() function which supports keyboard/AutoLISP input
  1360.   redirection and 'CAL, 'CP and Baseplane options.
  1361. -*/
  1362. /****************************************************************************/
  1363.  
  1364.  
  1365. int
  1366. /*FCN*/sa_getcorner(pt, prompt, result)
  1367.  
  1368.   ads_point pt;
  1369.   char      *prompt;
  1370.   ads_point result;
  1371. {
  1372.     int       success;
  1373.     ads_point p;
  1374.  
  1375.     success = get_it(/* NT */'C', pt, prompt, p);
  1376.     if (success == RTNORM)
  1377.         CPY_PNT(result, p);
  1378.     return(success);
  1379. } /*sa_getcorner*/
  1380.  
  1381.  
  1382. /****************************************************************************/
  1383. /*.doc sa_getangle(external)*/
  1384. /*+
  1385.   Enhanced ads_getangle() function which supports keyboard/AutoLISP input
  1386.   redirection and 'CAL, 'CP and Baseplane options.
  1387. -*/
  1388. /****************************************************************************/
  1389.  
  1390.  
  1391. int
  1392. /*FCN*/sa_getangle(pt, prompt, result)
  1393.  
  1394.   ads_point pt;
  1395.   char      *prompt;
  1396.   double    *result;
  1397. {
  1398.     int       success;
  1399.     ads_point p;
  1400.  
  1401.     success = get_it(/* NT */'A', pt, prompt, p);
  1402.  
  1403.     if (success == RTNORM)
  1404.         *result = p[X];
  1405.     return(success);
  1406. } /*sa_getangle*/
  1407.  
  1408.  
  1409. /****************************************************************************/
  1410. /*.doc sa_getorient(external)*/
  1411. /*+
  1412.   Enhanced ads_getorient() function which supports keyboard/AutoLISP input
  1413.   redirection and 'CAL, 'CP and Baseplane options.
  1414. -*/
  1415. /****************************************************************************/
  1416.  
  1417.  
  1418. int
  1419. /*FCN*/sa_getorient(pt, prompt, result)
  1420.  
  1421.   ads_point pt;
  1422.   char      *prompt;
  1423.   double    *result;
  1424. {
  1425.     int       success;
  1426.     ads_point p;
  1427.  
  1428.     success = get_it(/* NT */'O', pt, prompt, p);
  1429.     if (success == RTNORM)
  1430.         *result = p[X];
  1431.     return(success);
  1432. } /*sa_getorient*/
  1433.  
  1434.  
  1435. /****************************************************************************/
  1436. /*.doc sa_getdist(external)*/
  1437. /*+
  1438.   Enhanced ads_getdist() function which supports keyboard/AutoLISP input
  1439.   redirection and 'CAL, 'CP and Baseplane options.
  1440. -*/
  1441. /****************************************************************************/
  1442.  
  1443.  
  1444. int
  1445. /*FCN*/sa_getdist(pt, prompt, result)
  1446.  
  1447.   ads_point pt;
  1448.   char      *prompt;
  1449.   double    *result;
  1450. {
  1451.     int       success;
  1452.     ads_point p;
  1453.  
  1454.     success = get_it(/* NT */'D', pt, prompt, p);
  1455.     if (success == RTNORM)
  1456.         *result = p[X];
  1457.     return(success);
  1458. } /*sa_getdist*/
  1459.  
  1460.  
  1461. /****************************************************************************/
  1462. /*.doc sa_getreal(external)*/
  1463. /*+
  1464.   Enhanced ads_getreal() function which supports keyboard/AutoLISP input
  1465.   redirection and 'CAL, 'CP and Baseplane options.
  1466. -*/
  1467. /****************************************************************************/
  1468.  
  1469.  
  1470. int
  1471. /*FCN*/sa_getreal(prompt, result)
  1472.  
  1473.   char   *prompt;
  1474.   double *result;
  1475. {
  1476.     int       success;
  1477.     ads_point p;
  1478.  
  1479.     success = get_it(/* NT */'R', NULL, prompt, p);
  1480.     if (success == RTNORM)
  1481.         *result = p[X];
  1482.     return(success);
  1483. } /*sa_getreal*/
  1484.  
  1485.  
  1486. /****************************************************************************/
  1487. /*.doc sa_getint(external)*/
  1488. /*+
  1489.   Enhanced ads_getint() function which supports keyboard/AutoLISP input
  1490.   redirection and 'CAL, 'CP and Baseplane options.
  1491. -*/
  1492. /****************************************************************************/
  1493.  
  1494.  
  1495. int
  1496. /*FCN*/sa_getint(prompt, result)
  1497.  
  1498.   char *prompt;
  1499.   int  *result;
  1500. {
  1501.     int       success;
  1502.     ads_point p;
  1503.  
  1504.     success = get_it(/* NT */'I', NULL, prompt, p);
  1505.     *result = (int) p[X];
  1506.     return(success);
  1507. } /*sa_getint*/
  1508.  
  1509.  
  1510. /****************************************************************************/
  1511. /*.doc sa_getstring(external)*/
  1512. /*+
  1513.   Enhanced ads_getstring() function which supports keyboard/AutoLISP input
  1514.   redirection.
  1515. -*/
  1516. /****************************************************************************/
  1517.  
  1518.  
  1519. int
  1520. /*FCN*/sa_getstring(cronly, prompt, result)
  1521.  
  1522.   int  cronly;
  1523.   char *prompt;
  1524.   char *result;
  1525. {
  1526.     int success;
  1527.     int type;
  1528.  
  1529.     cp_used = FALSE;
  1530.  
  1531.     if (!lisp_input) {
  1532.         success = ads_getstring(cronly, prompt, result);
  1533.  
  1534.     } else {
  1535.         if (lisp_error)
  1536.             return(RTERROR);
  1537.  
  1538.         if ((current_rb == NULL) || (current_rb->restype == RTNIL)) {
  1539.             result[0] = EOS;
  1540.             success = RTNORM;
  1541.             goto End;
  1542.         }
  1543.  
  1544.         type = current_rb->restype;
  1545.  
  1546.         if (type == RTSTR) {
  1547.             if (!cronly && strchr(current_rb->resval.rstring, /* NT */' ')) {
  1548.                 ads_printf("\n┐∙╗~: ªrªΩñññúñ╣│\134┬°ª│íu¬┼Ñ╒ívíC\n\n");
  1549.                 success = RTERROR;
  1550.                 goto End;
  1551.             }
  1552.  
  1553.             strcpy(result, current_rb->resval.rstring);
  1554.             success = RTNORM;
  1555.         } else {
  1556.             ads_printf("\n┐∙╗~:íu░╤╝╞ív└│¼░íuªrªΩívíC\n\n");
  1557.             success = RTERROR;
  1558.         }
  1559.     }
  1560.  
  1561. End:
  1562.     if (lisp_input) {
  1563.         if (current_rb != NULL)
  1564.             current_rb = current_rb->rbnext;
  1565.         lisp_error = (success != RTNORM);
  1566.     }
  1567.  
  1568.     sa_get_returned_RTCAN = (success == RTCAN);
  1569.  
  1570.     sa_initget(0, NULL);
  1571.     return(success);
  1572. } /*sa_getstring*/
  1573.  
  1574.  
  1575. /****************************************************************************/
  1576. /*.doc sa_getkword(external)*/
  1577. /*+
  1578.   Enhanced ads_getkword() function which supports keyboard/AutoLISP input
  1579.   redirection.
  1580. -*/
  1581. /****************************************************************************/
  1582.  
  1583.  
  1584. int
  1585. /*FCN*/sa_getkword(prompt, result)
  1586.  
  1587.   char *prompt;
  1588.   char *result;
  1589. {
  1590.     int  success;
  1591.     int  type;
  1592.     char kw[MAX_STR_LEN];
  1593.  
  1594.     cp_used = FALSE;
  1595.  
  1596.     if (!lisp_input) {
  1597.         success = ads_getkword(prompt, result);
  1598.  
  1599.     } else {
  1600.  
  1601.         if (lisp_error)
  1602.             return(RTERROR);
  1603.  
  1604.         if (is_null_argument(&success))
  1605.             goto End;
  1606.  
  1607.         type = current_rb->restype;
  1608.  
  1609.         if (type == RTSTR) {
  1610.  
  1611.             check_if_string_is_keyword(current_rb->resval.rstring, kw);
  1612.  
  1613.             if (kw[0] != EOS) {       /*Keyword found*/
  1614.                 strcpy(result, kw);
  1615.                 success = RTNORM;
  1616.  
  1617.             } else if (initget_buffer.val & RSG_OTHER) {
  1618.                 strcpy(result, current_rb->resval.rstring);
  1619.                 str_toupper(result);
  1620.                 success = RTSTR;
  1621.  
  1622.             } else {
  1623.                 ads_printf("\n┐∙╗~: ╡L¬k┐δ├╤¬║íu├÷┴Σªr %sívíC\n\n",
  1624.                            current_rb->resval.rstring);
  1625.                 success = RTERROR;
  1626.             }
  1627.         } else {
  1628.             ads_printf("\n┐∙╗~:íu░╤╝╞ív└│¼░íu├÷┴ΣªrívíC\n\n");
  1629.             success = RTERROR;
  1630.         }
  1631.     }
  1632.  
  1633. End:
  1634.     if (lisp_input) {
  1635.         if (current_rb != NULL)
  1636.             current_rb = current_rb->rbnext;
  1637.         lisp_error = ((success != RTNORM) && (success != RTNONE));
  1638.     }
  1639.  
  1640.     sa_get_returned_RTCAN = (success == RTCAN);
  1641.  
  1642.     sa_initget(0, NULL);
  1643.     return(success);
  1644. } /*sa_getkword*/
  1645.  
  1646.  
  1647. /****************************************************************************/
  1648. /*.doc sa_getaxis(external)*/
  1649. /*+
  1650.   Function prompts for entering arbitrary 3D axis and returns two points
  1651.   p1 and p2 on the axis. The axis is oriented from p1 to p2.
  1652.  
  1653.   Function returns one the standard ADS result codes.
  1654. -*/
  1655. /****************************************************************************/
  1656.  
  1657.  
  1658. int
  1659. /*FCN*/sa_getaxis(prompt, p1, p2)
  1660.  
  1661.   char      *prompt;                  /* Prompt (optional)               */
  1662.   ads_point p1, p2;                   /* Returned two points on the axis */
  1663. {
  1664.     int       success;
  1665.     char      kw[10];
  1666.     ads_point origin, xaxis, yaxis, zaxis;
  1667.     char      pro[201];
  1668.  
  1669.     /* Prepare the prompt */
  1670.  
  1671.     if (prompt != NULL)
  1672.         strcpy(pro, prompt);
  1673.     else
  1674.         strcpy(pro, "Axis");
  1675.  
  1676.     strcat(pro, " ¿╠╛┌ E╣╧ñ╕/L│╠½ß/V╡°┤║/X╢b/Y╢b/Z╢b/<2┬I>: ");
  1677.  
  1678.     /* Get the method of specifying the axis */
  1679.  
  1680. Prompt:
  1681.  
  1682.     sa_initget(0, "Entity View Xaxis Yaxis Zaxis Last 2points");
  1683.     success = sa_getpoint(NULL, pro, origin);
  1684.  
  1685.     if (success == RTKWORD) {
  1686.         sa_getinput(kw);
  1687.     } else if (success == RTNONE) {
  1688.         strcpy(kw, "2points");
  1689.     } else if (success == RTNORM) {
  1690.         goto Second_point;
  1691.     } else {
  1692.         goto End;
  1693.     }
  1694.  
  1695.     /* Switch according to the method of specifying the axis */
  1696.  
  1697.     if (strcmp(kw, "2points") == 0) {
  1698.  
  1699.         sa_initget(1, NULL);
  1700.         success = sa_getpoint(NULL, "╢bñW▓─ 1 ┬I: ", origin);
  1701.         if (success != RTNORM)
  1702.             goto End;
  1703.  
  1704. Second_point:
  1705.         sa_initget(1, NULL);
  1706.         success = sa_getpoint(origin, "╢bñW▓─ 2 ┬I: ", zaxis);
  1707.         if (success != RTNORM)
  1708.             goto End;
  1709.  
  1710.         if (DISTANCE(origin, zaxis) < EPS) {
  1711.             ads_printf("\n¿Γ┬Iíu¼█ªPívíC\n\n");
  1712.             if (!lisp_input) {
  1713.                 goto Second_point;
  1714.             } else {
  1715.                 success = RTERROR;
  1716.                 goto End;
  1717.             }
  1718.         }
  1719.         success = RTNORM;
  1720.  
  1721.     } else if ((strcmp(kw, "Xaxis") == 0) ||
  1722.                (strcmp(kw, "Yaxis") == 0) ||
  1723.                (strcmp(kw, "Zaxis") == 0)   ) {
  1724.  
  1725.         char ax[2];
  1726.         char prompt[35];
  1727.  
  1728.         ax[0] = kw[0];
  1729.         ax[1] = EOS;
  1730.  
  1731.         strcpy(prompt, "┬Iª∞⌐≤ ");
  1732.         strcat(prompt, ax);
  1733.         strcat(prompt, " ╢b <0,0,0>: ");
  1734.  
  1735.         sa_initget(0, NULL);
  1736.         success = sa_getpoint(NULL, prompt, origin);
  1737.         if ((success != RTNORM) && (success != RTNONE))
  1738.             goto End;
  1739.  
  1740.         if (success == RTNONE) {
  1741.             origin[X] = origin[Y] = origin[Z] = 0.0;
  1742.             sa_cp2ucs(origin);
  1743.         }
  1744.  
  1745.         CPY_PNT(zaxis, origin);
  1746.         zaxis[kw[0] - /* NT */'X'] += 1.0;
  1747.         success = RTNORM;
  1748.  
  1749.     } else if (strcmp(kw, "View") == 0) {
  1750.  
  1751.         struct resbuf viewdir;
  1752.  
  1753.         sa_initget(0, NULL);
  1754.         success = sa_getpoint(NULL, "┬IÑXíu╡°┤║ñΦªVív¬║╢b <0,0,0>: ",
  1755.                               origin);
  1756.         if (success == RTNONE) {
  1757.             origin[X] = origin[Y] = origin[Z] = 0.0;
  1758.             sa_cp2ucs(origin);
  1759.         } else if (success != RTNORM)
  1760.             goto End;
  1761.  
  1762.         ads_getvar("VIEWDIR", &viewdir);
  1763.         ADD_PNT(zaxis, origin, viewdir.resval.rpoint);
  1764.         success = RTNORM;
  1765.  
  1766.     } else if (strcmp(kw, "Last") == 0) {
  1767.  
  1768.         if (DISTANCE(last_axis.p1, last_axis.p2) == 0.0) {
  1769.             ads_printf("\nѲ½e¿├Ñ╝½ⁿ⌐wíu╢bívíC\n\n");
  1770.             if (!lisp_input) {
  1771.                 goto Prompt;
  1772.             } else {
  1773.                 success = RTERROR;
  1774.                 goto End;
  1775.             }
  1776.         }
  1777.  
  1778.         sa_w2u(last_axis.p1, origin);
  1779.         sa_w2u(last_axis.p2, zaxis);
  1780.  
  1781.         success = RTNORM;
  1782.  
  1783.     } else {  /*Entity*/
  1784.  
  1785.         if (lisp_input) {
  1786. ads_printf("\n┐∙╗~:íuE╣╧ñ╕ív┐∩╢╡ñúÑi╕gÑ╤ AutoLISP ÑsÑ╬íC\n");
  1787.             success = RTERROR;
  1788.             goto End;
  1789.         }
  1790.  
  1791.         success = sa_get_cs_of_picked_entity(NULL, TRUE,
  1792.                                              origin, xaxis, yaxis, zaxis);
  1793.         if (success != RTNORM) {
  1794.             success = RTERROR;
  1795.             goto End;
  1796.         }
  1797.  
  1798.         sa_orientate_cs_upwards(origin, xaxis, yaxis, zaxis);
  1799.         success = RTNORM;
  1800.     }
  1801.  
  1802.     if (success == RTNORM) {
  1803.  
  1804.         CPY_PNT(p1, origin);
  1805.         CPY_PNT(p2, zaxis);
  1806.  
  1807.         sa_u2w(p1, last_axis.p1);
  1808.         sa_u2w(p2, last_axis.p2);
  1809.     }
  1810.  
  1811. End:
  1812.     if (lisp_input) {
  1813.         lisp_error = (success != RTNORM);
  1814.     }
  1815.     sa_get_returned_RTCAN = (success == RTCAN);
  1816.  
  1817.     return(success);
  1818. } /*sa_getaxis*/
  1819.  
  1820.  
  1821. /****************************************************************************/
  1822. /*.doc sa_getplane(external)*/
  1823. /*+
  1824.   Function prompts for entering an arbitrary plane and returns three points
  1825.   on the plane. These three points may also be considered as defining
  1826.   a coordinate system:
  1827.  
  1828.     p1 ... origin
  1829.     p2 ... point on positive portion of X-axis
  1830.     p3 ... point in the halfplane of positive Y-axis
  1831.  
  1832.   Function returns one of the standard ADS result codes.
  1833. -*/
  1834. /****************************************************************************/
  1835.  
  1836.  
  1837. int
  1838. /*FCN*/sa_getplane(prompt, plane_option, p1, p2, p3)
  1839.  
  1840.   char      *prompt;                  /* Prompt (optional)               */
  1841.   char      *plane_option;            /* NULL or "Entity", "3points" ... */
  1842.   ads_point p1, p2, p3;               /* Returned points on the plane    */
  1843. {
  1844.     int        success;
  1845.     char       kw[10];
  1846.     ads_point  origin, xaxis, yaxis, zaxis;
  1847.  
  1848.     if ((plane_option != NULL) && (plane_option[0] != EOS)) {
  1849.  
  1850.         /* Use directly the provided plane option */
  1851.  
  1852.         strcpy(kw, plane_option);
  1853.  
  1854.     } else {
  1855.         char pro[201];
  1856.  
  1857.         /* Prepare the prompt */
  1858.  
  1859.         if (prompt != NULL)
  1860.             strcpy(pro, prompt);
  1861.         else
  1862.             strcpy(pro, "Plane");
  1863.  
  1864.         strcat(pro, " ¿╠╛┌ E╣╧ñ╕/L│╠½ß/Z╢b/V╡°┤║/XY/YZ/ZX/<3┬I>: ");
  1865.  
  1866.         /* Get the method of specifying the plane */
  1867. Prompt:
  1868.         sa_initget(0, "Entity View Zaxis XY YZ ZX Last 3points");
  1869.  
  1870.         success = sa_getpoint(NULL, pro, origin);
  1871.  
  1872.         if (success == RTKWORD) {
  1873.             sa_getinput(kw);
  1874.         } else if (success == RTNONE) {
  1875.             strcpy(kw, "3points");
  1876.         } else if (success == RTNORM) {
  1877.             goto Second_point;
  1878.         } else {
  1879.             goto End;
  1880.         }
  1881.     }
  1882.  
  1883.     /* Switch according the method of specifying the plane */
  1884.  
  1885.     if (strcmp(kw, "3points") == 0) {
  1886.  
  1887.         sa_initget(1, NULL);
  1888.         success = sa_getpoint(NULL, "¡▒ñW▓─ 1 ┬I: ", origin);
  1889.         if (success != RTNORM)
  1890.             goto End;
  1891.  
  1892. Second_point:
  1893.         sa_initget(1, NULL);
  1894.         success = sa_getpoint(origin, "¡▒ñW▓─ 2 ┬I: ", xaxis);
  1895.         if (success != RTNORM)
  1896.             goto End;
  1897.  
  1898.         if (DISTANCE(origin, xaxis) < EPS) {
  1899.             ads_printf("\n▓─ 1 ┬I╗P▓─ 2 ┬Iíu¼█ªPívíC\n\n");
  1900.             if (!lisp_input) {
  1901.                 goto Second_point;
  1902.             } else {
  1903.                 success = RTERROR;
  1904.                 goto End;
  1905.             }
  1906.         }
  1907.  
  1908. Third_point:
  1909.         sa_initget(1, NULL);
  1910.         success = sa_getpoint(origin, "¡▒ñW▓─ 3 ┬I: ", yaxis);
  1911.         if (success != RTNORM)
  1912.             goto End;
  1913.  
  1914.         if (DISTANCE(xaxis, yaxis) < EPS) {
  1915.             ads_printf("\n▓─ 2 ┬I╗P▓─ 3 ┬Iíu¼█ªPívíC\n\n");
  1916.             if (!lisp_input) {
  1917.                 goto Third_point;
  1918.             } else {
  1919.                 success = RTERROR;
  1920.                 goto End;
  1921.             }
  1922.         }
  1923.         if (DISTANCE(origin, yaxis) < EPS) {
  1924.             ads_printf("\n▓─ 1 ┬I╗P▓─ 3 ┬Iíu¼█ªPívíC\n\n");
  1925.             if (!lisp_input) {
  1926.                 goto Third_point;
  1927.             } else {
  1928.                 success = RTERROR;
  1929.                 goto End;
  1930.             }
  1931.         }
  1932.         if (sa_points_are_collinear(origin, xaxis, yaxis)) {
  1933.             ads_printf("\nñT┬Iª@╜uíC\n\n");
  1934.             if (!lisp_input) {
  1935.                 goto Third_point;
  1936.             } else {
  1937.                 success = RTERROR;
  1938.                 goto End;
  1939.             }
  1940.         }
  1941.         success = RTNORM;
  1942.  
  1943.     } else if (strcmp(kw, "Zaxis") == 0) {
  1944.  
  1945.         sa_initget(1, NULL);
  1946.         success = sa_getpoint(NULL, "¡▒ñW¬║┬I: ", origin);
  1947.         if (success != RTNORM)
  1948.             goto End;
  1949.  
  1950. Zaxis_point:
  1951.         sa_initget(1, NULL);
  1952.         success = sa_getpoint(origin,
  1953.                               "┬IÑXÑ¡¡▒¬║íuZ ╢bív(¬k╜u): ",
  1954.                               zaxis);
  1955.         if (success != RTNORM)
  1956.             goto End;
  1957.  
  1958.         if (DISTANCE(origin, zaxis) < EPS) {
  1959.             ads_printf("\n¿Γ┬Iíu¼█ªPívíC\n\n");
  1960.             if (!lisp_input) {
  1961.                 goto Zaxis_point;
  1962.             } else {
  1963.                 success = RTERROR;
  1964.                 goto End;
  1965.             }
  1966.         }
  1967.         sa_plane_from_point_and_normal(origin, zaxis, xaxis, yaxis);
  1968.         success = RTNORM;
  1969.  
  1970.     } else if (strcmp(kw, "View") == 0) {
  1971.  
  1972.         struct resbuf viewdir;
  1973.  
  1974.         sa_initget(0, NULL);
  1975.         success = sa_getpoint(NULL, "┬IÑXíu╡°┤║Ñ¡¡▒ív<0,0,0>: ", origin);
  1976.         if (success == RTNONE) {
  1977.             origin[X] = origin[Y] = origin[Z] = 0.0;
  1978.             sa_cp2ucs(origin);
  1979.         } else if (success != RTNORM)
  1980.             goto End;
  1981.  
  1982.         ads_getvar("VIEWDIR", &viewdir);
  1983.         ADD_PNT(zaxis, origin, viewdir.resval.rpoint);
  1984.  
  1985.         /* Get the 'xaxis' and 'yaxis' aligned with x,y axes of the screen */
  1986.  
  1987.         {
  1988.             struct resbuf ucs, dcs;
  1989.             ads_point     xv, yv;
  1990.  
  1991.             xv[X] = 1.0;
  1992.             xv[Y] = 0.0;
  1993.             xv[Z] = 0.0;
  1994.  
  1995.             yv[X] = 0.0;
  1996.             yv[Y] = 1.0;
  1997.             yv[Z] = 0.0;
  1998.  
  1999.             ucs.restype     = RTSHORT;
  2000.             ucs.resval.rint = 1;
  2001.             dcs.restype     = RTSHORT;
  2002.             dcs.resval.rint = 2;
  2003.  
  2004.             success = ads_trans(xv, &dcs, &ucs, TRUE, xv);
  2005.             if (success != RTNORM)
  2006.                 goto End;
  2007.  
  2008.             success = ads_trans(yv, &dcs, &ucs, TRUE, yv);
  2009.             if (success != RTNORM)
  2010.                 goto End;
  2011.  
  2012.             ADD_PNT(xaxis, origin, xv);
  2013.             ADD_PNT(yaxis, origin, yv);
  2014.         }
  2015.         success = RTNORM;
  2016.  
  2017.     } else if ((strcmp(kw, "XY") == 0) ||
  2018.                (strcmp(kw, "YZ") == 0) ||
  2019.                (strcmp(kw, "ZX") == 0)   ) {
  2020.  
  2021.         int  i;
  2022.         char pl[3];
  2023.         char prompt[35];
  2024.  
  2025.         pl[0] = kw[0];
  2026.         pl[1] = kw[1];
  2027.         pl[2] = EOS;
  2028.  
  2029.         strcpy(prompt, "┬IÑX ");
  2030.         strcat(prompt, pl);
  2031.         strcat(prompt, " Ñ¡¡▒ <0,0,0>: ");
  2032.  
  2033.         sa_initget(0, NULL);
  2034.         success = sa_getpoint(NULL, prompt, origin);
  2035.         if ((success != RTNORM) && (success != RTNONE))
  2036.             goto End;
  2037.  
  2038.         if (success == RTNONE) {
  2039.             origin[X] = origin[Y] = origin[Z] = 0.0;
  2040.             sa_cp2ucs(origin);
  2041.         }
  2042.  
  2043.         CPY_PNT(xaxis, origin);
  2044.         CPY_PNT(yaxis, origin);
  2045.  
  2046.         i = kw[0] - /* NT */'X';
  2047.  
  2048.         xaxis[i]       += 1.0;
  2049.         yaxis[(i+1)%3] += 1.0;
  2050.         success = RTNORM;
  2051.  
  2052.     } else if (strcmp(kw, "Last") == 0) {
  2053.  
  2054.         if ((DISTANCE(last_plane.p1, last_plane.p2) == 0.0) &&
  2055.             (DISTANCE(last_plane.p1, last_plane.p3) == 0.0)   ) {
  2056.  
  2057.             ads_printf("\nѲ½e¿├Ñ╝½ⁿ⌐wíuÑ¡¡▒ívíC\n\n");
  2058.             if (!lisp_input) {
  2059.                 goto Prompt;
  2060.             } else {
  2061.                 success = RTERROR;
  2062.                 goto End;
  2063.             }
  2064.         }
  2065.  
  2066.         sa_w2u(last_plane.p1, origin);
  2067.         sa_w2u(last_plane.p2, xaxis );
  2068.         sa_w2u(last_plane.p3, yaxis );
  2069.  
  2070.         success = RTNORM;
  2071.  
  2072.     } else if (strcmp(kw, "Entity") == 0) {
  2073.  
  2074.         if (lisp_input) {
  2075. ads_printf("┐∙╗~:íuE╣╧ñ╕ív┐∩╢╡ñúÑi╕gÑ╤ AutoLISP ÑsÑ╬íC\n");
  2076.             success = RTERROR;
  2077.             goto End;
  2078.         }
  2079.  
  2080.         success = sa_get_cs_of_picked_entity(NULL, FALSE,
  2081.                                              origin, xaxis, yaxis, zaxis);
  2082.         if (success != RTNORM)
  2083.             goto End;
  2084.         success = RTNORM;
  2085.  
  2086.     } else {
  2087.         success = RTERROR;
  2088.         goto End;
  2089.     }
  2090.  
  2091. End:
  2092.     if (success == RTNORM) {
  2093.  
  2094.         CPY_PNT(p1,origin);
  2095.         CPY_PNT(p2,xaxis);
  2096.         CPY_PNT(p3,yaxis);
  2097.  
  2098.         sa_u2w(p1, last_plane.p1);
  2099.         sa_u2w(p2, last_plane.p2);
  2100.         sa_u2w(p3, last_plane.p3);
  2101.     }
  2102.  
  2103.     if (lisp_input) {
  2104.         lisp_error = (success != RTNORM);
  2105.     }
  2106.     sa_get_returned_RTCAN = (success == RTCAN);
  2107.  
  2108.     return(success);
  2109. } /*sa_getplane*/
  2110.  
  2111.  
  2112. /****************************************************************************/
  2113. /*.doc sa_set_cp(external)*/
  2114. /*+
  2115.   Function prompts the user to enter a CP (Construction Plane) and sets
  2116.   current UCS according to this CP. Function may be invoked consecutively
  2117.   several times.
  2118.  
  2119.   This function may also be called from any sa_getxxx() function to change
  2120.   the UCS. To do so, the keyword "Baseplane" must be provided as the first
  2121.   keyword in sa_initget's list of accepted keywords.  Then, if the user
  2122.   types "Baseplane", sa_set_cp() function is called. Example:
  2123.  
  2124.   sa_initget(1 + 2, "Baseplane Aaa Bbb");
  2125.   sa_getpoint(...)  <-- If the user types Baseplane, sa_set_cp() is called
  2126.  
  2127.   To return UCS back, that is to undo the effect of sa_set_cp(),
  2128.   call sa_return_cp().
  2129.  
  2130.   Note: See the AME R2 manual for examples of using the Baseplane option
  2131.         for creating the primitive solids.
  2132.  
  2133.   Function returns one of the standard ADS result codes.
  2134. -*/
  2135. /****************************************************************************/
  2136.  
  2137.  
  2138. int
  2139. /*FCN*/sa_set_cp(prompt)
  2140.  
  2141.   char *prompt;                       /* Prompt (optional) */
  2142. {
  2143.     int       success;
  2144.     ads_point p1, p2, p3;
  2145.  
  2146.     success = sa_getplane(prompt, NULL, p1, p2, p3);
  2147.     if (success != RTNORM)
  2148.         goto End;
  2149.  
  2150.     sa_save_acad_vars();
  2151.     success = ads_command(RTSTR, /* NT */"_.UCS", RTSTR, /* NT */"_3",
  2152.                           RT3DPOINT, p1, RT3DPOINT, p2, RT3DPOINT, p3, 0);
  2153.     sa_restore_acad_vars();
  2154.  
  2155.     if (success != RTNORM)
  2156.         goto End;
  2157.  
  2158.     setcp_level++;
  2159.     ucs_level  ++;
  2160.  
  2161.     /* Set 'UCSICON' variable to "On" and "Origin" */
  2162.  
  2163.     if (setcp_level == 1) {
  2164.  
  2165.         struct resbuf ucsi;
  2166.  
  2167.         ads_getvar("UCSICON", &ucsicon);
  2168.         ucsi.restype     = RTSHORT;
  2169.         ucsi.resval.rint = 3;         /* "On" and "Origin" */
  2170.         ads_setvar("UCSICON",&ucsi);
  2171.     }
  2172.     success = RTNORM;
  2173.  
  2174. End:
  2175.     if (lisp_input) {
  2176.         lisp_error = (success != RTNORM);
  2177.     }
  2178.     sa_get_returned_RTCAN = (success == RTCAN);
  2179.     return(success);
  2180. } /*sa_set_cp*/
  2181.  
  2182.  
  2183. /****************************************************************************/
  2184. /*.doc sa_return_cp(external)*/
  2185. /*+
  2186.   Inverts the efect of ALL sa_set_cp() calls, that it it returns UCS to its
  2187.   original position before the first sa_set_cp() was used.
  2188.  
  2189.   Function returns one of the standard ADS result codes.
  2190. -*/
  2191. /****************************************************************************/
  2192.  
  2193.  
  2194. int
  2195. /*FCN*/sa_return_cp()
  2196. {
  2197.     int           success;
  2198.     int           i;
  2199.     struct resbuf ucsi;
  2200.  
  2201.     if (setcp_level > 0) {
  2202.  
  2203.         /* Hide UCSICON to avoid jumping */
  2204.  
  2205.         ucsi.restype     = RTSHORT;
  2206.         ucsi.resval.rint = 0;
  2207.         ads_setvar("UCSICON", &ucsi);
  2208.  
  2209.         sa_cmdecho_off();
  2210.         for (i = 0; i < setcp_level; i++) {
  2211.  
  2212.             success = ads_command(RTSTR, /* NT */"_.UCS", RTSTR,
  2213.                                   /* NT */"_PREV", 0);
  2214.             if (success != RTNORM)
  2215.                 break;
  2216.         }
  2217.         sa_cmdecho_back();
  2218.  
  2219.         ads_setvar("UCSICON", &ucsicon);
  2220.     }
  2221.  
  2222.     setcp_level = 0;
  2223.     ucs_level   = 0;
  2224.  
  2225.     return(success);
  2226. } /*sa_return_cp*/
  2227.  
  2228.  
  2229. /****************************************************************************/
  2230. /*.doc sa_cp2ucs(external)*/
  2231. /*+
  2232.   If CP was used in the last sa_getxxx() function, then this function
  2233.   converts point 'p' expressed in the coordinate sytem of the last CP to
  2234.   current UCS, otherwise leaves the point unchanged.
  2235.  
  2236.   This function can be used, for example, when sa_getpoint() function
  2237.   returns RTNONE and you want to use default point coordinates with
  2238.   respect to the CP used. Then the default coordinates must be transformed
  2239.   by the sa_cp2ucs() function.
  2240.  
  2241.   Function returns one of the standard ADS result codes.
  2242. -*/
  2243. /****************************************************************************/
  2244.  
  2245.  
  2246. int
  2247. /*FCN*/sa_cp2ucs(p)
  2248.  
  2249.   ads_point p;
  2250. {
  2251.     int       success;
  2252.     ads_point pp1, pp2, pp3;
  2253.  
  2254.     if (!cp_used || (p == NULL) ||
  2255.         sa_points_are_collinear(last_plane.p1, last_plane.p2, last_plane.p3))
  2256.     {
  2257.         return(RTNORM);
  2258.     }
  2259.  
  2260.     /* Convert the last plane from WCS to UCS (because UCS command expects
  2261.        coordinates in current UCS).
  2262.     */
  2263.  
  2264.     sa_w2u(last_plane.p1, pp1);
  2265.     sa_w2u(last_plane.p2, pp2);
  2266.     sa_w2u(last_plane.p3, pp3);
  2267.  
  2268.     /* Set UCS to align with the last plane */
  2269.  
  2270.     sa_save_acad_vars();
  2271.     success = ads_command(RTSTR, /* NT */"_.UCS", RTSTR, /* NT */"_3P",
  2272.                           RT3DPOINT, pp1, RT3DPOINT, pp2, RT3DPOINT, pp3,
  2273.                           0);
  2274.  
  2275.     /* Convert the given point 'p' from CP (now current UCS) to WCS */
  2276.  
  2277.     sa_u2w(p, p);
  2278.  
  2279.     /* Return UCS back */
  2280.  
  2281.     ads_command(RTSTR, /* NT */"_.UCS", RTSTR, /* NT */"_PREV", 0);
  2282.     sa_restore_acad_vars();
  2283.  
  2284.     if (success != RTNORM)
  2285.         return(RTERROR);
  2286.  
  2287.     /* Convert 'p' from WCS to current UCS */
  2288.  
  2289.     sa_w2u(p, p);
  2290.  
  2291.     return(RTNORM);
  2292. } /*sa_cp2ucs*/
  2293.  
  2294.  
  2295. /****************************************************************************/
  2296. /*.doc sa_ssget(external)*/
  2297. /*+
  2298.   Enhanced ads_ssget() function providing keyboard/AutoLISP input
  2299.   redirection.
  2300.  
  2301.   Note:
  2302.  
  2303.   The sa_ssget() function supports the Implied selection set better than
  2304.   the standard ads_ssget(). The sa_init_input() function reads the implied
  2305.   selection set and keeps it in the global variable implied_selset. The
  2306.   global integer variable implied_selset_exists is set to TRUE if there was
  2307.   an implied selection set. Then the first call to sa_ssget() uses this
  2308.   stored selection set and sets the global variable implied_selset_exists
  2309.   to FALSE.
  2310.  
  2311.   The advantage of this solution is that you may execute any number of
  2312.   ads_command() calls before actually calling sa_ssget() and still you
  2313.   can get the implied selection set. Using the standard ads_ssget() wouldn't
  2314.   work as any call to ads_command() clears the implied selection set and
  2315.   ads_ssget() wouldn't be able to get it.
  2316. -*/
  2317. /****************************************************************************/
  2318.  
  2319.  
  2320. int
  2321. /*FCN*/sa_ssget(str, pt1, pt2, filter, ss)
  2322.  
  2323.   char          *str;
  2324.   void          *pt1;
  2325.   ads_point     pt2;
  2326.   struct resbuf *filter;
  2327.   ads_name      ss;
  2328. {
  2329.     int  success;
  2330.     int  type;
  2331.     int  NULL_params;
  2332.     int  implied_required = FALSE;
  2333.     char kw[MAX_STR_LEN];
  2334.  
  2335.     NULL_params = ((str == NULL) && (pt1 == NULL) && (pt2 == NULL) &&
  2336.                    (filter == NULL));
  2337.  
  2338.     /* Check whether the input 'str' is "IMPLIED" */
  2339.  
  2340.     if ((str != NULL) && (strlen(str) <= 7)) {
  2341.         int  i;
  2342.         char imp[8];
  2343.  
  2344.         strcpy(imp, "IMPLIED");
  2345.         implied_required = TRUE;
  2346.         for (i = 0 ; i < strlen(str); i++)
  2347.             if (ads_toupper(str[i]) != imp[i]) {
  2348.                 implied_required = FALSE;
  2349.                 break;
  2350.             }
  2351.     }
  2352.  
  2353.     if (implied_required) {
  2354.         if (implied_selset_exists) {
  2355.             ads_name_set(implied_selset, ss);
  2356.             implied_selset_exists = FALSE;
  2357.             success = RTNORM;
  2358.         } else {
  2359.             success = RTERROR;
  2360.         }
  2361.  
  2362.     } else if (implied_selset_exists && NULL_params) {
  2363.         ads_name_set(implied_selset, ss);
  2364.         implied_selset_exists = FALSE;
  2365.         success = RTNORM;
  2366.  
  2367.     } else if (!lisp_input || !NULL_params) {
  2368.         success = ads_ssget(str, pt1, pt2, filter, ss);
  2369.  
  2370.     } else {
  2371.  
  2372.         if (lisp_error)
  2373.             return(RTERROR);
  2374.  
  2375.         initget_buffer.val = 0;
  2376.         if (is_null_argument(&success))
  2377.             goto End;
  2378.  
  2379.         type = current_rb->restype;
  2380.         switch (type) {
  2381.  
  2382.         case RTPICKS:
  2383.             ads_name_set(current_rb->resval.rlname, ss);
  2384.             success = RTNORM;
  2385.             break;
  2386.  
  2387.         case RTENAME:
  2388.             success = ads_ssadd(current_rb->resval.rlname, NULL, ss);
  2389.             if (success != RTNORM)
  2390.                 success = RTERROR;
  2391.             break;
  2392.  
  2393.         case RTSTR:
  2394.             check_if_string_is_keyword(current_rb->resval.rstring, kw);
  2395.  
  2396.             if (kw[0] != EOS) {
  2397.                 strcpy(initget_buffer.kw, kw);
  2398.                 success = RTKWORD;
  2399.             } else {
  2400.                 ads_printf("\n┐∙╗~: ╡L¬k┐δ├╤¬║íu├÷┴Σªr %sívíC\n\n",
  2401.                            current_rb->resval.rstring);
  2402.                 success = RTERROR;
  2403.             }
  2404.             break;
  2405.  
  2406.         default:
  2407.             ads_printf("\n┐∙╗~: └│¼░íu┐∩╢░ (selection set)ívíC\n\n");
  2408.             success = RTERROR;
  2409.             break;
  2410.         } /*switch*/
  2411.     }
  2412.  
  2413. End:
  2414.     if (lisp_input) {
  2415.         if (current_rb != NULL)
  2416.             current_rb = current_rb->rbnext;
  2417.  
  2418.         if (!implied_required) {
  2419.             lisp_error = ((success != RTNORM) &&
  2420.                           (success != RTNONE) &&
  2421.                           (success != RTKWORD));
  2422.         }
  2423.     }
  2424.  
  2425.     if (success == RTNORM) {
  2426.         ads_name_set(ss, ssget_ss[no_of_ssget_ss]);
  2427.         no_of_ssget_ss++;
  2428.     }
  2429.  
  2430.     sa_get_returned_RTCAN = (success == RTCAN);
  2431.  
  2432.     return(success);
  2433. } /*sa_ssget*/
  2434.  
  2435.  
  2436. /****************************************************************************/
  2437. /*.doc sa_entsel(external)*/
  2438. /*+
  2439.   Enhanced ads_entsel() function supporting keyboard/AutoLISP input
  2440.   redirection.
  2441.  
  2442.   When reading input from AutoLISP, either an single entity name or
  2443.   a list (entity_name pickpt) is accepted. If only an entity name is
  2444.   provided, then the pickpoint 'ptres' is not assigned.
  2445. -*/
  2446. /****************************************************************************/
  2447.  
  2448.  
  2449. int
  2450. /*FCN*/sa_entsel(str, entres, ptres)
  2451.  
  2452.   char      *str;
  2453.   ads_name  entres;
  2454.   ads_point ptres;
  2455. {
  2456.     int  success;
  2457.     int  type;
  2458.     int  getpoint_called = FALSE;
  2459.     char kw[MAX_STR_LEN];
  2460.  
  2461.     if (!lisp_input) {
  2462.         success = ads_entsel(str, entres, ptres);
  2463.  
  2464.     } else {
  2465.  
  2466.         if (lisp_error)
  2467.             return(RTERROR);
  2468.  
  2469.         if (current_rb == NULL) {
  2470.             ads_printf("\n┐∙╗~:íuñ▐╝╞ív╣Lñ╓íC\n\n");
  2471.             success = RTERROR;
  2472.             goto End;
  2473.         }
  2474.  
  2475.         type = current_rb->restype;
  2476.         switch (type) {
  2477.  
  2478.         case RTENAME:
  2479.             /* Entity name provided */
  2480.  
  2481.             ads_name_set(current_rb->resval.rlname, entres);
  2482.  
  2483.             success = RTNORM;
  2484.             break;
  2485.  
  2486.         case RTLB:
  2487.             /* A list (entity_name point) provided */
  2488.  
  2489.             current_rb = current_rb->rbnext;
  2490.             if ((current_rb != NULL) && (current_rb->restype == RTENAME)) {
  2491.                 ads_name_set(current_rb->resval.rlname, entres);
  2492.             } else {
  2493.                 ads_printf("\n┐∙╗~: └│¼░ (entity_name pickpt) ªΩªCíC\n\n");
  2494.                 success = RTERROR;
  2495.                 break;
  2496.             }
  2497.  
  2498.             current_rb = current_rb->rbnext;
  2499.             if ((current_rb != NULL)                &&
  2500.                 ((current_rb->restype == RT3DPOINT) ||
  2501.                  (current_rb->restype == RTPOINT))) {
  2502.                 ads_point_set(ptres, current_rb->resval.rpoint);
  2503.             } else {
  2504.                 ads_printf("\n┐∙╗~: └│¼░ (entity_name pickpt) ªΩªCíC\n\n");
  2505.                 success = RTERROR;
  2506.                 break;
  2507.             }
  2508.  
  2509.             current_rb = current_rb->rbnext;
  2510.             if ((current_rb == NULL) || (current_rb->restype != RTLE)) {
  2511.                 ads_printf("\n┐∙╗~: └│¼░ (entity_name pickpt) ªΩªCíC\n\n");
  2512.                 success = RTERROR;
  2513.                 break;
  2514.             }
  2515.  
  2516.             success = RTNORM;
  2517.             break;
  2518.  
  2519.         case RTSTR:
  2520.             check_if_string_is_keyword(current_rb->resval.rstring, kw);
  2521.  
  2522.             if (kw[0] != EOS) {
  2523.                 strcpy(initget_buffer.kw, kw);
  2524.                 success = RTKWORD;
  2525.             } else {
  2526.                 ads_printf("\n┐∙╗~: ╡L¬k┐δ├╤íu├÷┴Σªr %sívíC\n\n",
  2527.                            current_rb->resval.rstring);
  2528.                 success = RTERROR;
  2529.             }
  2530.             break;
  2531.  
  2532.         default:
  2533.             ads_printf("\n┐∙╗~: └│¼░íu╣╧ñ╕ívíC\n\n");
  2534.             success = RTERROR;
  2535.             goto End;
  2536.         } /*switch*/
  2537.     }
  2538.  
  2539. End:
  2540.     if (lisp_input) {
  2541.         if ((current_rb != NULL) && !getpoint_called)
  2542.             current_rb = current_rb->rbnext;
  2543.         lisp_error = ((success != RTNORM) && (success != RTKWORD));
  2544.     }
  2545.  
  2546.     sa_get_returned_RTCAN = (success == RTCAN);
  2547.  
  2548.     return(success);
  2549. } /*sa_entsel*/
  2550.  
  2551.  
  2552. /****************************************************************************/
  2553. /*.doc se_reset_last_axis_and_plane(external)*/
  2554. /*+
  2555.   Resets the values of the last_axis and last_plane static variables to
  2556.   "no axis" and "no plane".
  2557. -*/
  2558. /****************************************************************************/
  2559.  
  2560.  
  2561. void
  2562. /*FCN*/sa_reset_last_axis_and_plane()
  2563. {
  2564.     ads_point zero;
  2565.     zero[X] = zero[Y] = zero[Z] = 0.0;
  2566.  
  2567.     CPY_PNT(last_axis.p1, zero);
  2568.     CPY_PNT(last_axis.p2, zero);
  2569.  
  2570.     CPY_PNT(last_plane.p1, zero);
  2571.     CPY_PNT(last_plane.p2, zero);
  2572.     CPY_PNT(last_plane.p3, zero);
  2573. } /*sa_reset_last_axis_and_plane*/
  2574.  
  2575.