;;;Código fuente del libro "Experto AutoCAD con Visual LISP"
;;; (c) 2012 Ediciones ARTUAL, S.L. Barcelona, España.
;;; (c) 2012-2020 Reinaldo Togores. Todos los derechos reservados
;;; Se permite su uso mencionando la obra y su autor.
;;;CapÃtulo 23. Medios de asociar información a los Objetos Gráficos.
(defun ent-lee-atributos (noment / ent lista txt)Â
  (setq ent (entget noment))
  (ifÂ
    (and (equal (cdr (assoc 0 ent)) "INSERT")Â
         (> (cdr (assoc 66 ent)) 0))
    (progn (setq ent (entget (entnext noment)))Â
           (while (not (= (cdr (assoc 0 ent)) "SEQEND"))Â
             (foreach dato entÂ
               (if (or (= (car dato) 1) (= (car dato) 3))Â
                 (setq txt (cons (cdr dato) txt))))
             (setq lista (consÂ
                           (cons (cdr (assoc 2 ent))Â
                                 (sustituyeÂ
                                   ""
                                   "\\P"
                                   (apply 'strcat (reverse txt))))
                           lista)
                   ent   (entget (entnext (cdr (assoc -1 ent))))))))
  (reverse lista))
;;;Listado 23.1. Función que lee los atributos variables de un bloque.
(defun prp-lee-atributos (ename / ent lista txt)Â
  (setq ent (entget ename))
  (ifÂ
    (and (equal (cdr (assoc 0 ent)) "INSERT")Â
         (> (cdr (assoc 66 ent)) 0))
    (prognÂ
      (setq ent (entnext ename))
      (while (not (= (cdr (assoc 0 (entget ent))) "SEQEND"))Â
        (setq valor (getpropertyvalue ent "Value")
              lista (consÂ
                      (cons (getpropertyvalue ent "Tag")Â
                            (if (vl-string-search "\\P" valor)Â
                              (sustituye " " "\\P" valor)
                              valor))
                      lista)
              ent   (entnext ent)))))
  (reverse lista))
;;;Listado 23.2. Función no-Com que lee los atributos variables de un bloque.
(defun ax-extrae-atrib (bloque constante / atributos lista)Â
  (setq atributos (vlax-variant-valueÂ
                    (if constanteÂ
                      (vla-getconstantattributes bloque)
                      (vla-getattributes bloque))))
  (if (>= (vlax-safearray-get-u-bound atributos 1) 0)Â
    (foreach atrib (vlax-safearray->list atributos)Â
      (setq lista (consÂ
                    (cons (vlax-get-property atrib "TagString")Â
                          (ifÂ
                            (= (vla-get-MTextAttribute atrib)Â
                               :vlax-true)
                            (sustituyeÂ
                              ""
                              "\\P"
                              (vlax-get-property atrib "TextString"))
                            (vlax-get-property atrib "TextString")))
                    lista))))
  lista)
;;;Listado 23.3. Función estándar para extraer valores de atributos.
(defun ax-lee-atributos (noment / bloque resultado)Â
  (setq bloque (vlax-ename->vla-object noment))
  (setq resultado (vl-catch-all-applyÂ
                    'vla-get-HasAttributes
                    (list bloque)))
  (if (eq resultado :vlax-true)Â
    (append (reverse (ax-extrae-atrib bloque t))Â
            (reverse (ax-extrae-atrib bloque nil)))))
;;;Listado 23.4. Procesamiento de un bloque para extraer una lista con sus atributos.
(defun ent-datosx (noment nomaplic lis-id lis-val / datos lista objeto)Â
  (if (not (tblsearch "appid" nomaplic))Â
    (regapp nomaplic))
  (setq datos (listÂ
                -3
                (cons nomaplicÂ
                      (foreach term (mapcar 'strcat lis-id lis-val)Â
                        (setq lista (append listaÂ
                                            (list (cons 1000 term))))))))
  (setq objeto (append (entget noment) (list datos)))
  (entmod objeto))
;;;Listado 23.5. Asignación de XDATA.
(defun ent-lee-datosx (noment nomaplic id como-cadena / val)Â
  (setq id  (strcat id "=*")
        val (cdarÂ
              (vl-remove-if-notÂ
                '(lambda (x) (wcmatch (cdr x) id))
                (cdadr (assoc -3 (entget noment (list nomaplic)))))))
  (if valÂ
    (progn (setq val (vl-string-left-trim id val))Â
           (if como-cadenaÂ
             val
             (read val)))))
;;;Listado 23.6. Lectura de XDATA.
(defun lista-dicc ()Â
  (mapcar 'cdrÂ
          (vl-remove-if-notÂ
            '(lambda (x) (= (car x) 3))
            (entget (namedobjdict)))))
;;;Listado 23.7. Obtención de  la lista de todos los diccionarios.
(defun entrada-datos (/ ent nombre lista)Â
  (whileÂ
    (and (setq ent (car (entsel "\nDesigne entidad a nombrar: ")))Â
         (setq nombre (getstring t "\nIndique Nombre: "))
         (not (= nombre "")))
    (setq lista (cons (cons (cdr (assoc 5 (entget ent))) nombre)Â
                      lista)))
  lista)
;;;Listado 23.8. Función para solicitar los datos al usuario.
(defun crea-dicc (nombre)Â
  (if (not (member nombre (lista-dicc)))Â
    (dictadd (namedobjdict)Â
             nombre
             (entmakex '((0 . "DICTIONARY") (100 . "AcDbDictionary"))))
    (cdr (assoc -1 (dictsearch (namedobjdict) nombre)))))
;;;Listado 23.9. Función que crea el diccionario o recupera su ENAME en caso de existir.
(defun nuevos-registros (ent-dicc lista-datos / xrec)Â
  (foreach dato lista-datosÂ
    (if (dictsearch ent-dicc (car dato))Â
      (entdel (dictremove ent-dicc (car dato))))
    (ifÂ
      (setq xrec (entmakexÂ
                   (list '(0 . "XRECORD")Â
                         '(100 . "AcDbXrecord")
                         (cons 1 (cdr dato)))))
      (dictadd ent-dicc (car dato) xrec)
      (prompt "\error en adición de campo"))))
;;;Listado 23.10. Adición de nuevos registros al diccionario.
(defun C:TOPONIMICOS (/ datos dicc)Â
  (condÂ
    ((setq dicc (dictsearch (namedobjdict) "TOPONIMICOS"))
     (setq dicc (cdr (assoc -1 dicc))))
    ((setq dicc (crea-dicc "TOPONIMICOS")))
    (t
     (prompt "\nError en la creación del diccionario TOPONOIMICOS")))
  (if (and dicc (setq datos (entrada-datos)))Â
    (nuevos-registros dicc datos)
    (alert "Se ha producido un error en la aplicación"))
  (princ))
;;;Listado 23.11. Comando C:TOPONIMICOS.
(defun C:IDENTIFICA (/ dicc ent nom)Â
  (ifÂ
    (and (setq dicc (dictsearch (namedobjdict) "TOPONIMICOS"))Â
         (setq dicc (cdr (assoc -1 dicc))))
    (while (setq ent (car (entsel "\nDesigne entidad a identificar: ")))Â
      (if (setq nom (dictsearch dicc (cdr (assoc 5 (entget ent)))))Â
        (alertÂ
          (strcat "La entidad seleccionada representa\n"Â
                  (cdr (assoc 1 nom))))
        (alert "La entidad no tiene\nnombre asignado.")))))
;;;Listado 23.12. Función para consulta de los datos asociados.
(defun C:BORRA-NOMBRE (/ dicc ent)Â
  (ifÂ
    (and (setq dicc (dictsearch (namedobjdict) "TOPONIMICOS"))Â
         (setq dicc (cdr (assoc -1 dicc))))
    (setq ent (carÂ
                (entselÂ
                  "\nSeleccione la entidad cuyo nombre desea eliminar: "))))
  (setq ent (cdr (assoc 5 (entget ent))))
  (if (dictsearch dicc ent)Â
    (entdel (dictremove dicc ent))
    (alert "La entidad no tiene\nnombre asignado.")))
;;;Listado 23.12a. Función que elimina el toponÃmico asociado.
(defun lista->ldata (dicc lista)Â
  (foreach sublista listaÂ
    (if (listp sublista)Â
      (vlax-ldata-putÂ
        dicc
        (vl-princ-to-string (car sublista))
        (cdr sublista)))))
;;;Listado 23.13. Función lista->ldata.
(defun lista->ldata (dicc lista)Â
  (foreach sublista listaÂ
    (if (and (listp sublista) (vlax-ldata-test (cdr sublista)))Â
      (vlax-ldata-putÂ
        dicc
        (vl-princ-to-string (car sublista))
        (cdr sublista)))))
;;;Listado 23.14. Función LISTA->LDATA incorporando VLAX-LDATA-TEST.
(defun asocia (ent-ppal ent-asoc clave)Â
  (vlax-ldata-put ent-ppal clave ent-asoc))
;;;Listado 23.15. Función para asociar entidades mediante LDATA.
(defun localiza-ADO-CAO (/ dir lcid versCAOdir ADOdir)
  (setq dir    (getenv "COMMONPROGRAMFILES")
        ADOdir (findfile (strcat dir "\\system\\ado\\msado15.dll"))
        lcid   (vla-get-LocaleID (vlax-get-acad-object))
        vers   (if (> (atoi (getvar "ACADVER")) 19)Â
                 "20"
                 "16")
        CAOdir (findfileÂ
                 (strcatÂ
                   dir
                   "\\AUTODESK SHARED\\"
                   (condÂ
                     ((= lcid 1028) (strcat "cao" vers "cht.tlb"))
                     ((= lcid 1029) (strcat "cao" vers "csy.tlb"))
                     ((= lcid 1031) (strcat "cao" vers "deu.tlb"))
                     ((= lcid 1034) (strcat "cao" vers "esp.tlb"))
                     ((= lcid 1036) (strcat "cao" vers "fra.tlb"))
                     ((= lcid 1038) (strcat "cao" vers "hun.tlb"))
                     ((= lcid 1040) (strcat "cao" vers "ita.tlb"))
                     ((= lcid 1041) (strcat "cao" vers "jpn.tlb"))
                     ((= lcid 1042) (strcat "cao" vers "kor.tlb"))
                     ((= lcid 1046) (strcat "cao" vers "ptb.tlb"))
                     ((= lcid 1049) (strcat "cao" vers "rus.tlb"))
                     ((= lcid 2052) (strcat "cao" vers "chs.tlb"))
                     (t (strcat "cao" vers "enu.tlb"))))))
  (list ADOdir CAOdir))
;;;Listado 23.16. Función que busca las trayectorias de las bibliotecas.
(defun importa-ADO-CAO (/ bibl)Â
  (vl-load-com)
  (setq bibl (localiza-ADO-CAO))
  (if (car bibl)Â
    (condÂ
      ((vl-member-ifÂ
         '(lambda (x) (wcmatch x "ADOM-*"))
         (atoms-family 1))
       t)
      (t
       (vlax-import-type-libraryÂ
         :tlb-filename
         (car bibl)
         :methods-prefix
         "adoM-"
         :properties-prefix
         "adoP-"
         :constants-prefix
         "adoC-")))
    (prompt "\nERROR: No se encontró la biblioteca ADO"))
  (if (last bibl)Â
    (condÂ
      ((vl-member-ifÂ
         '(lambda (x) (wcmatch x "CAOM-*"))
         (atoms-family 1))
       t)
      (t
       (vlax-import-type-libraryÂ
         :tlb-filename
         (last bibl)
         :methods-prefix
         "caoM-"
         :properties-prefix
         "caoP-"
         :constants-prefix
         "caoC-")))
    (prompt "\nERROR: No se encontró la biblioteca CAO.")))
;;;Listado 23.16. Función que importa bibliotecas de componentes.