lunes, 27 de mayo de 2024

Protege tus Fotos con Facilidad: Cómo Añadir Marcas de Agua Usando Bash con antiX

 En el mundo digital de hoy, proteger tus imágenes es más importante que nunca. Con el aumento del contenido en línea, es crucial garantizar que tu trabajo esté protegido contra el uso no autorizado. Una forma efectiva de hacerlo es mediante la aplicación de marcas de agua a tus imágenes.


marca_agua_graciela_sanz_color_blanco.png

Pero, ¿qué ocurre cuando tienes cientos, o incluso miles de imágenes que necesitan ser protegidas? Ahí es donde entra en juego la automatización.

Con el siguiente script en bash, simplificamos el proceso de aplicación de marcas de agua a gran escala. Veamos cómo funciona.

El script recorre cada imagen en el directorio especificado, obteniendo su tamaño y calculando automáticamente el tamaño proporcional de la marca de agua.


Fotografía con marca de agua

Luego, redimensiona la marca de agua para que se ajuste perfectamente a cada imagen, eliminando cualquier perfil de color incrustado para garantizar una aplicación limpia y consistente.

Finalmente, aplica la marca de agua al pie de cada imagen, con un margen inferior centrado para una presentación elegante y profesional.

Con este proceso automatizado, puedes proteger tus imágenes de manera eficiente y confiable, manteniendo tu trabajo seguro y protegido en todo momento.


Fotografía con marca de agua

 
#!/bin/bash

# --------------------------------------------------------------------------------------------------------------------------------------
# File: aplicar_marca_agua.sh
# By Julio Alberto Lascano http://drcalambre.blogspot.com/
#________          _________        .__                ___.                  
#\______ \_______  \_   ___ \_____  |  | _____    _____\_ |_________   ____  
# |    |  \_  __ \ /    \  \/\__  \ |  | \__  \  /     \| __ \_  __ \_/ __ \ 
# |    `   \  | \/ \     \____/ __ \|  |__/ __ \|  Y Y  \ \_\ \  | \/\  ___/ 
#/_______  /__|     \______  (____  /____(____  /__|_|  /___  /__|    \___  >
#        \/                \/     \/          \/      \/    \/            \/ 
# --------------------------------------------------------------------------------------------------------------------------------------
# Last modified:2024-05-28
# --------------------------------------------------------------------------------------------------------------------------------------
# Descripción del script: aplicar_marca_agua.sh
# --------------------------------------------------------------------------------------------------------------------------------------
# Uso: aplicar_marca_agua.sh -m [marca_agua] -d [directorio_imagenes] -s [factor_escala] -o [directorio_salida]
# --------------------------------------------------------------------------------------------------------------------------------------
# Este script automatiza el proceso de aplicar una marca de agua a todas las imágenes en un directorio especificado.
# A continuación se explica paso a paso lo que hace el script:
#
# 1. Verificación de comandos de ImageMagick:
#    - Se verifica si los comandos 'identify', 'convert' y 'composite' están disponibles.
#
# 2. Definición de parámetros:
#    - MARCA_DE_AGUA: Ruta de la imagen que se utilizará como marca de agua.
#    - DIRECTORIO_IMAGENES: Directorio que contiene las imágenes a las que se aplicará la marca de agua.
#    - FACTOR_ESCALA: Factor de escala que determina el tamaño proporcional de la marca de agua en relación con el ancho de la imagen original.
#    - DIRECTORIO_SALIDA: Directorio donde se guardarán las imágenes con la marca de agua aplicada.
#
# 3. Verificación de parámetros y rutas:
#    - Se verifica que todos los parámetros necesarios se han proporcionado.
#    - Se verifica que la ruta de la marca de agua y el directorio de imágenes existen.
#    - Si el directorio de salida no existe, se crea automáticamente.
#
# 4. Bucle para procesar cada imagen:
#    - Se utiliza un bucle 'for' para iterar sobre cada archivo en el directorio de imágenes especificado.
#    - Se verifica si el archivo actual en el bucle es un archivo regular utilizando la condición 'if [ -f "$IMAGEN" ]'.
#
# 5. Obtención del tamaño de la imagen:
#    - Se utiliza el comando 'identify' para obtener el tamaño de la imagen en píxeles.
#
# 6. Cálculo del tamaño de la marca de agua:
#    - Se calcula el tamaño de la marca de agua proporcional al tamaño de la imagen original, utilizando el factor de escala definido.
#
# 7. Redimensionamiento de la marca de agua:
#    - Se redimensiona la marca de agua al tamaño calculado y se elimina cualquier perfil de color incrustado para evitar advertencias.
#
# 8. Aplicación de la marca de agua:
#    - Se aplica la marca de agua al pie de la imagen con un margen inferior centrado utilizando el comando 'composite'.
#
# 9. Eliminación de archivos temporales:
#    - Se elimina el archivo temporal de la marca de agua redimensionada después de aplicarla a la imagen.
# --------------------------------------------------------------------------------------------------------------------------------------


# Verificación de comandos de ImageMagick
if ! command -v identify &> /dev/null || ! command -v convert &> /dev/null || ! command -v composite &> /dev/null
then
    echo "ImageMagick no está instalado o los comandos necesarios no están disponibles. Por favor, instálalo antes de ejecutar este script."
    exit 1
fi

# Manejo de errores
# Se añade manejo de errores para asegurar que el script se detenga si ocurre algún problema. 
# Se hace con: set -e lo que hace que el script termine si algún comando falla.

set -e

# Uso: aplicar_marca_agua.sh -m [marca_agua] -d [directorio_imagenes] -s [factor_escala] -o [directorio_salida]
while getopts "m:d:s:o:" opt; do
    case ${opt} in
        m ) MARCA_DE_AGUA=$OPTARG ;;
        d ) DIRECTORIO_IMAGENES=$OPTARG ;;
        s ) FACTOR_ESCALA=$OPTARG ;;
        o ) DIRECTORIO_SALIDA=$OPTARG ;;
        \? ) echo "Uso: aplicar_marca_agua.sh -m [marca_agua] -d [directorio_imagenes] -s [factor_escala] -o [directorio_salida]"
             exit 1 ;;
    esac
done

# Verificación de parámetros
if [ -z "$MARCA_DE_AGUA" ] || [ -z "$DIRECTORIO_IMAGENES" ] || [ -z "$FACTOR_ESCALA" ] || [ -z "$DIRECTORIO_SALIDA" ]; then
    echo ""
    echo "Uso: aplicar_marca_agua.sh -m [marca_agua] -d [directorio_imagenes] -s [factor_escala] -o [directorio_salida]"
    echo ""
    echo "Todos los parámetros (-m, -d, -s, -o) son obligatorios."
    echo "-------------------------------------------------------------------------------------------------------------"
    echo "Factor de escala para el tamaño de la marca de agua -s [factor_escala]"
    echo "Por ejemplo: -s 0.15 , un factor de escala del 15% es adecuado para la fotografia de paisajes."
    echo "-------------------------------------------------------------------------------------------------------------"
    
    
    exit 1
fi

# Verificación de la existencia de la ruta de la marca de agua
if [ ! -f "$MARCA_DE_AGUA" ]; then
    echo "La ruta de la marca de agua ($MARCA_DE_AGUA) no existe."
    exit 1
fi

# Verificación de la existencia del directorio de imágenes
if [ ! -d "$DIRECTORIO_IMAGENES" ]; then
    echo "El directorio de imágenes ($DIRECTORIO_IMAGENES) no existe."
    exit 1
fi

# Verificación de la existencia del directorio de salida
if [ ! -d "$DIRECTORIO_SALIDA" ]; then
    echo "El directorio de salida ($DIRECTORIO_SALIDA) no existe. Creando el directorio..."
    mkdir -p "$DIRECTORIO_SALIDA"
fi

contador=0
tiempo_inicio=$(date +%s)


# Aplicar marca de agua a cada imagen en el directorio
for IMAGEN in "$DIRECTORIO_IMAGENES"/*; do
    if [ -f "$IMAGEN" ] && file --mime-type "$IMAGEN" | grep -q -E "image/(png|gif|jpeg|jpg)"; then
        nombre_imagen=$(basename "$IMAGEN")
        
        # La expresión ${nombre_imagen##*.} utiliza un mecanismo de expansión de parámetros en el shell 
        # de Unix para extraer la extensión de un nombre de archivo.
        # Significa eliminar todo hasta el último punto en el nombre del archivo, y devolver lo que queda.
        
        extension_imagen="${nombre_imagen##*.}"
        
        echo "Aplicando marca de agua a $DIRECTORIO_IMAGENES$nombre_imagen -> $DIRECTORIO_SALIDA${nombre_imagen%.*}_wm.$extension_imagen"
        #echo "Aplicando marca de agua a $DIRECTORIO_IMAGENES/$nombre_imagen -> $DIRECTORIO_SALIDA/${nombre_imagen%.*}_wm.$extension_imagen"
        
        # Obtener el tamaño de la imagen (ancho x altura)
        tamano_imagen=$(identify -format "%wx%h" "$IMAGEN")
        
        # Separar el ancho y la altura
        ancho_imagen=$(echo "$tamano_imagen" | cut -d'x' -f 1)
        altura_imagen=$(echo "$tamano_imagen" | cut -d'x' -f 2)
        
        # Calcular el tamaño de la marca de agua proporcional al tamaño de la imagen
        tamano_marca=$(echo "$ancho_imagen * $FACTOR_ESCALA" | bc)
        
        # Redimensionar la marca de agua al tamaño calculado y eliminar el perfil de color
        marca_de_agua_redimensionada=$(mktemp)
        convert "$MARCA_DE_AGUA" -resize "${tamano_marca}x${tamano_marca}" -strip "$marca_de_agua_redimensionada"
        
        # Aplicar marca de agua al pie de la imagen con margen inferior centrado
        composite -dissolve 50% -gravity South -geometry +0+3 "$marca_de_agua_redimensionada" "$IMAGEN" "$DIRECTORIO_SALIDA/${nombre_imagen%.*}_wm.$extension_imagen"
        
        # Eliminar el archivo temporal de la marca de agua redimensionada
        rm "$marca_de_agua_redimensionada"
        
        # Incrementar el contador por cada imagen procesada
		contador=$((contador + 1))
    fi
done

# Calcular el tiempo total transcurrido
tiempo_fin=$(date +%s)
tiempo_total=$((tiempo_fin - tiempo_inicio))

# Convertir tiempo total a formato hh:mm:ss
horas=$((tiempo_total / 3600))
minutos=$(( (tiempo_total % 3600) / 60 ))
segundos=$((tiempo_total % 60))

# Mostrar el total de imágenes procesadas y el tiempo que tomó
echo "-------------------------------------------------------------------------------------------------------------"
echo "Total de imágenes procesadas: $contador"
# Formatear la salida
printf "Tiempo total transcurrido: %02d:%02d:%02d\n" $horas $minutos $segundos




Para utilizar el script en Debian, necesitas tener instalados los siguientes paquetes:

ImageMagick: Este paquete proporciona las herramientas identify, convert, y composite, que se utilizan en el script para manipular imágenes y aplicar la marca de agua.
Para instalar estos paquetes en Debian, puedes usar el siguiente comando:
 
sudo apt-get update
sudo apt-get install imagemagick bc



miércoles, 15 de mayo de 2024

Solucion para antiX (Bookworm) para "Warning: Key is stored in legacy trusted.gpg keyring" del repositorio de mxlinux

Un poco de historia

MX Linux efectivamente utiliza componentes principales de antiX, junto con software adicional desarrollado o empaquetado por la comunidad de MX. La colaboración entre las comunidades de antiX y la antigua MEPIS en el desarrollo de MX Linux explica la conexión entre estas distribuciones.

El nombre "MX" mismo refleja esta colaboración, combinando la "M" de MEPIS y la "X" de antiX. Este reconocimiento subraya las raíces compartidas y los esfuerzos colaborativos detrás de MX Linux, aprovechando las fortalezas y componentes de ambas distribuciones para crear una experiencia Linux fácil de usar y estable.

Por lo tanto, MX Linux no se basa únicamente en Debian, sino que incorpora componentes clave de antiX, lo que la convierte en una combinación única de la estabilidad de Debian con mejoras personalizadas de su comunidad de desarrollo colaborativo.

https://mxlinux.org/

El Mensaje

El mensaje "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8))" indica que el comando apt-key, utilizado para manejar claves de repositorio en sistemas basados en Debian, está ahora considerado obsoleto y se recomienda utilizar un enfoque diferente para administrar las claves de manera más segura y eficiente.

En lugar de usar apt-key, se aconseja ahora gestionar los archivos de claves en el directorio trusted.gpg.d. Este directorio contiene archivos individuales que representan las claves de los repositorios de software. Puedes agregar, eliminar o modificar claves colocando archivos en este directorio.

La documentación asociada con el mensaje te proporcionará más detalles sobre cómo utilizar este nuevo método de administración de claves. Es importante seguir estas recomendaciones para mantener un sistema actualizado y seguro.

MX Linux un sistema operativo basado en las versiones de Debian estable que utiliza componentes centrales de antiX, y por lo tanto mantiene un repositorio para antix.

Esta seria mi lista de repositorios para la version antiX (basada en Debian 12 Bookworm)


En particular me voy a enfocar en el repositorio de MX Linux (antix.list)
 
# Use with Debian Bookworm repositories. 
deb https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm/ bookworm main nosystemd nonfree


Cuando se tienen repositorios adicionales, distintos a los oficiales (por ejemplo, mxlinux) es que las llaves que validan los paquetes están en el antiguo archivo trusted.gpg y se muestra el siguiente WARNING: luego de hacer un apt update.
 
Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for detail

La solución 

Extraer la llave del archivo /etc/apt/trusted.gpg
 
root@antix1:/etc/apt/sources.list.d# apt-key list
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
/etc/apt/trusted.gpg
--------------------
pub   rsa2048 2013-03-13 [SC] [caduca: 2027-04-06]
      ED57 48AC 0E57 5DD2 49A5  6B84 DB36 CDF3 452F 0C20
uid        [desconocida] antiX Linux repo 
uid        [desconocida] antiX (antix repo) 
sub   rsa2048 2013-03-13 [E] [caduca: 2027-04-06]

/etc/apt/trusted.gpg.d/debian-archive-bookworm-automatic.asc
------------------------------------------------------------
pub   rsa4096 2023-01-21 [SC] [caduca: 2031-01-19]
      B8B8 0B5B 623E AB6A D877  5C45 B7C5 D7D6 3509 47F8
uid        [desconocida] Debian Archive Automatic Signing Key (12/bookworm) 
sub   rsa4096 2023-01-21 [S] [caduca: 2031-01-19]

/etc/apt/trusted.gpg.d/debian-archive-bookworm-security-automatic.asc
---------------------------------------------------------------------
pub   rsa4096 2023-01-21 [SC] [caduca: 2031-01-19]
      05AB 9034 0C0C 5E79 7F44  A8C8 254C F3B5 AEC0 A8F0
uid        [desconocida] Debian Security Archive Automatic Signing Key (12/bookworm) 
sub   rsa4096 2023-01-21 [S] [caduca: 2031-01-19]

/etc/apt/trusted.gpg.d/debian-archive-bookworm-stable.asc
---------------------------------------------------------
pub   ed25519 2023-01-23 [SC] [caduca: 2031-01-21]
      4D64 FEC1 19C2 0290 67D6  E791 F8D2 585B 8783 D481
uid        [desconocida] Debian Stable Release Key (12/bookworm) 

/etc/apt/trusted.gpg.d/debian-archive-bullseye-automatic.asc
------------------------------------------------------------
pub   rsa4096 2021-01-17 [SC] [caduca: 2029-01-15]
      1F89 983E 0081 FDE0 18F3  CC96 73A4 F27B 8DD4 7936
uid        [desconocida] Debian Archive Automatic Signing Key (11/bullseye) 
sub   rsa4096 2021-01-17 [S] [caduca: 2029-01-15]

/etc/apt/trusted.gpg.d/debian-archive-bullseye-security-automatic.asc
---------------------------------------------------------------------
pub   rsa4096 2021-01-17 [SC] [caduca: 2029-01-15]
      AC53 0D52 0F2F 3269 F5E9  8313 A484 4904 4AAD 5C5D
uid        [desconocida] Debian Security Archive Automatic Signing Key (11/bullseye) 
sub   rsa4096 2021-01-17 [S] [caduca: 2029-01-15]

/etc/apt/trusted.gpg.d/debian-archive-bullseye-stable.asc
---------------------------------------------------------
pub   rsa4096 2021-02-13 [SC] [caduca: 2029-02-11]
      A428 5295 FC7B 1A81 6000  62A9 605C 66F0 0D6C 9793
uid        [desconocida] Debian Stable Release Key (11/bullseye) 

/etc/apt/trusted.gpg.d/debian-archive-buster-automatic.asc
----------------------------------------------------------
pub   rsa4096 2019-04-14 [SC] [caduca: 2027-04-12]
      80D1 5823 B7FD 1561 F9F7  BCDD DC30 D7C2 3CBB ABEE
uid        [desconocida] Debian Archive Automatic Signing Key (10/buster) 
sub   rsa4096 2019-04-14 [S] [caduca: 2027-04-12]

/etc/apt/trusted.gpg.d/debian-archive-buster-security-automatic.asc
-------------------------------------------------------------------
pub   rsa4096 2019-04-14 [SC] [caduca: 2027-04-12]
      5E61 B217 265D A980 7A23  C5FF 4DFA B270 CAA9 6DFA
uid        [desconocida] Debian Security Archive Automatic Signing Key (10/buster) 
sub   rsa4096 2019-04-14 [S] [caduca: 2027-04-12]

/etc/apt/trusted.gpg.d/debian-archive-buster-stable.asc
-------------------------------------------------------
pub   rsa4096 2019-02-05 [SC] [caduca: 2027-02-03]
      6D33 866E DD8F FA41 C014  3AED DCC9 EFBF 77E1 1517
uid        [desconocida] Debian Stable Release Key (10/buster) 

/etc/apt/trusted.gpg.d/debian-ports-archive-2023.gpg
----------------------------------------------------
pub   rsa4096 2021-12-30 [SC] [caducó: 2024-02-01]
      D0C9 87D7 BEC3 EDDF 8948  6CC2 B523 E5F3 FC4E 5F2C
uid        [  caducada ] Debian Ports Archive Automatic Signing Key (2023) 

/etc/apt/trusted.gpg.d/debian-ports-archive-2024.gpg
----------------------------------------------------
pub   rsa4096 2023-01-07 [SC] [caduca: 2025-02-01]
      01C2 D6F3 D1A4 6AD1 C0DC  2F3D 8D69 6746 88B6 CB36
uid        [desconocida] Debian Ports Archive Automatic Signing Key (2024) 

/etc/apt/trusted.gpg.d/debian-ports-archive-2025.gpg
----------------------------------------------------
pub   rsa4096 2024-01-05 [SC] [caduca: 2026-02-01]
      5197 59FB C670 BFA6 C87E  4241 3AF6 5F93 D6FB C5B9
uid        [desconocida] Debian Ports Archive Automatic Signing Key (2025) 

/etc/apt/trusted.gpg.d/deb-multimedia-keyring.gpg
-------------------------------------------------
pub   rsa4096 2014-03-05 [SC]
      A401 FF99 368F A1F9 8152  DE75 5C80 8C2B 6555 8117
uid        [desconocida] Christian Marillat 
uid        [desconocida] Christian Marillat 
uid        [desconocida] Christian Marillat 
sub   rsa4096 2014-03-05 [E]

root@antix1:/etc/apt/sources.list.d# 

Identificamos el repositorio antix que causa el conflicto que de la lista de arriba sería este:
 
pub   rsa2048 2013-03-13 [SC] [caduca: 2027-04-06]
      ED57 48AC 0E57 5DD2 49A5  6B84 DB36 CDF3 452F 0C20
uid        [desconocida] antiX Linux repo 
uid        [desconocida] antiX (antix repo) 
sub   rsa2048 2013-03-13 [E] [caduca: 2027-04-06]


La llave (se conforma con los ultimos 8 caracteres) se exportará en un temporal para evitar que el siguiente paso la borre del llavero.
 
root@antix1:/etc/apt/sources.list.d# apt-key export 452F0C20 | gpg --dearmor -o /tmp/antix.gpg

Borrar la clave (se conforma con los ultimos 8 caracteres) del antiguo llavero
 
root@antix1:/etc/apt/sources.list.d# apt-key del 452F0C20
OK

Incluir la llave exportada en el actual sistema
 
root@antix1:/etc/apt/sources.list.d# mv /tmp/antix.gpg /etc/apt/keyrings/

Indicar en el repositorio antix.list la clave a utilizar
 
# Use with Debian Bookworm repositories. 
deb [signed-by=/etc/apt/keyrings/antix.gpg] https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm/ bookworm main nosystemd nonfree

La indicación signed-by le permite al comando apt encontrar qué nombre se le puso al archivo de la llave que validará el repositorio de paquetes y a su vez, permite colocar los archivos en cualquier lugar (Debian ofrece la carpeta /etc/apt/keyrings/ para este fin) 

Si ahora realizamos la actualización veremos que el repositorio mxlinux.unc.edu.ar ya no indica ningún conflicto con la llave.
 
root@antix1:/etc/apt/sources.list.d# apt update
Obj:1 http://security.debian.org bookworm-security InRelease
Obj:2 http://deb.debian.org/debian bookworm-backports InRelease                                                                            
Des:3 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm InRelease [27,4 kB]                                                       
Obj:4 http://www.deb-multimedia.org bookworm InRelease                                                                                     
Obj:5 http://ftp.cl.debian.org/debian bookworm-updates InRelease
Obj:6 http://ftp.cl.debian.org/debian bookworm InRelease
Des:7 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm/nosystemd i386 Packages [223 kB]
Des:8 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm/nosystemd amd64 Packages [224 kB]
Des:9 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm/nonfree i386 Packages [9.765 B]
Des:10 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm/nonfree amd64 Packages [9.423 B]
Des:11 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm/main amd64 Packages [329 kB]
Des:12 https://mxlinux.unc.edu.ar/mxlinux/antix/bookworm bookworm/main i386 Packages [312 kB]
Descargados 1.135 kB en 4s (262 kB/s)                      
Leyendo lista de paquetes... Hecho
Creando árbol de dependencias... Hecho
Leyendo la información de estado... Hecho
Se pueden actualizar 5 paquetes. Ejecute «apt list --upgradable» para verlos.
root@antix1:/etc/apt/sources.list.d# 

sábado, 13 de abril de 2024

icewm-remember-settings

GUI para gestionar tamaño y posición de cualquier ventana en icewm (escrito en bash, aparece en la versión 23 de antix. es compatible con versiones anteriores de antix). 



Un script de Bash diseñado para interactuar con la configuración de ventanas del gestor de ventanas IceWM. Este script permite a los usuarios guardar y restaurar configuraciones específicas de ventanas, como la geometría, el espacio de trabajo y la capa de una ventana. Además, ofrece funcionalidades para seleccionar y listar ventanas abiertas, y para mostrar una ventana de ayuda. Un análisis de las diferentes secciones y funcionalidades del script:

1. **Variables Iniciales y Configuración de Localización**:
   - Define dónde IceWM buscará los archivos de idioma.
   - Define algunas variables para controlar la interacción con la ventana, como el foco inicial y si se deben listar o seleccionar ventanas.

2. **Procesamiento de Argumentos**:
   - El script procesa argumentos de línea de comandos para ajustar las variables `select` y `list` que controlan si el script actúa en modo selección o listado.

3. **Localización del Archivo de Configuración (`winoptions`)**:
   - Intenta localizar el archivo `winoptions` en diferentes directorios configurados a través de variables de entorno o rutas comunes, para determinar dónde guardar las configuraciones de las ventanas.

4. **Funciones Definidas**:
   - `select_window`: Restablece el script para seleccionar una ventana cuando se lo invoque.
   - `save_changes`: Guarda o elimina configuraciones de una ventana basadas en la información temporal almacenada y luego elimina el archivo temporal.
   - `help_dialog`: Muestra una ventana de diálogo de ayuda utilizando `yad`, una herramienta para crear cuadros de diálogo GTK.
   - `list_dialog`: Lista todas las ventanas abiertas permitiendo al usuario seleccionar una para configurar.
   - `main_dialog`: Es la función principal que interactúa con el usuario para obtener configuraciones de ventana, mostrar y manipular datos, y llamar a `save_changes` si es necesario.

5. **Ciclo Principal de Ejecución**:
   - El script entra en un bucle controlado por la variable `loop`.
   - Dentro del bucle, dependiendo de las variables `select` y `list`, llama a las funciones `main_dialog` o `list_dialog` para procesar o interactuar con las ventanas.
   - El script puede terminar o continuar basado en interacciones del usuario y si se seleccionó alguna opción de listado o selección de ventanas.

6. **Limpieza Final**:
   - Limpia y elimina las funciones y variables de ayuda para evitar que se ejecuten o muestren de nuevo.

### Aspectos Notables y Consideraciones:

- **Flexibilidad y Personalización**: El script ofrece varias formas de interactuar con la configuración de ventanas de IceWM, lo que lo hace útil para usuarios que desean tener un control más fino sobre el comportamiento de su entorno de escritorio.
 

- **Dependencia de Herramientas Externas**: Dependencias como `yad`, `wmctrl`, e `icesh` son cruciales para la funcionalidad del script. Asegúrate de que estas herramientas estén instaladas en el sistema donde se ejecuta el script.
 

- **Manejo de Archivos Temporales**: El script hace un uso extenso de archivos temporales para manejar la configuración y los datos de las ventanas, lo cual es práctico pero requiere asegurarse de que se limpian adecuadamente para evitar residuos o fugas de información.
 

- **Robustez**: El script verifica la existencia de directorios y archivos antes de proceder, lo cual es una buena práctica para evitar errores de ejecución.

En resumen, el script es una herramienta avanzada para gestionar configuraciones específicas de ventanas en IceWM, diseñada para ser utilizada por usuarios que quieran optimizar su experiencia de usuario en entornos Linux con IceWM.


 
#!/bin/bash
# -*- mode:sh -*-
#
# This program is based on BobC's, PPC's and icewm team's effort.
#

# localization
TEXTDOMAINDIR=/usr/share/locale
TEXTDOMAIN=icewm-remember-settings

#initial values
focus="-f"
select=0
list=0
loop=1

# check for extra options
while [[ $# -ge 1 ]]
do
    case $1 in
        (-s) select=1 ;;
        (-l) list=1 ;;
    esac
    shift
done

# locate winoptions
if [[ -d $ICEWM_PRIVCFG ]]
then
	winoptions=$ICEWM_PRIVCFG/winoptions
elif [[ -d $XDG_CONFIG_HOME && -d $XDG_CONFIG_HOME/icewm ]]
then
	winoptions=$XDG_CONFIG_HOME/icewm/winoptions
elif [[ -d $HOME/.config/icewm ]]
then
	winoptions=$HOME/.config/icewm/winoptions
elif [[ -d $HOME/.icewm ]]
then
	winoptions=$HOME/.icewm/winoptions
else
	echo "$0: Cannot find your icewm config directory" >&2
	exit 1
fi

#function to call again this program, but having the user click on the specific window
select_window(){
	echo "selecting window"
	# remove temporary file
	rm -f -- "$temp"
	#give select option
	select=1
	focus=
	loop=1
}

#function to add/remove changes
save_changes(){
	# delete all previous data for the program
	#delete geometry
	sed -i -e "/$cls_geo/d" "$winoptions"
	#delete layer
	sed -i -e "/$cls_lay/d" "$winoptions"
	#delete workspace
	sed -i -e "/$cls_wsp/d" "$winoptions"
	
	# add new selected information for the program, reading the temp file
    while IFS= read -r line
	do
		# geometry
		if [[ "$line" == "geometry" ]]
		then
			# add new
			echo "$new_geo" >> "$winoptions"
		fi
		# layer
		if [[ "$line" == "layer" ]]
		then
			# add new
			echo "$new_lay" >> "$winoptions"
		fi
		# workspace
		if [[ "$line" == "workspace" ]]
		then
			# add new
			echo "$new_wsp" >> "$winoptions"
		fi
	done < "$temp"
	
	# remove temporary file
	rm -f -- "$temp"
	
	# let icewm reload the winoptions
	icesh winoptions
	
	#stop select option
	select=0
	
	#if list not selected, stop loop
	if [[ list -eq 0 ]]; then
	loop=0
	fi
}

#launches help window
help_dialog()
{
	yad --image="gtk-dialog-info" --height=250 --width=400 --scroll \
	--title=$"HELP" --class="IceWM-remember-settings" --name="help" --borders=10 --center \
	--form --field=$"Save the size and position, workspace \
and layer of a window using the IceWM-remember-settings app.":LBL '' \
	--field=$"Next time you launch the program, it will remember the \
window properties last saved.":LBL '' \
	--field=$"You can also delete this information unticking all options.":LBL '' \
	--field=$"Use the Select other option to select a different \
window/program to configure.":LBL '' --separator="" --button=gtk-quit:0 --buttons-layout=center
}

#launches list dialog
list_dialog(){
	#List names of all currently open windows (we may have to exclude Conky from the list) - Original version over at: https://pastebin.com/13em3H11
	wmctrl -l|awk '{$3=""; $2=""; $1=""; print $0}' > /tmp/windowlist.txt
	#Window to be exluded from the list:
	#exclude_from_window_list="Conky (dhc"
	grep -v "Conky (" /tmp/windowlist.txt > /tmp/windowlist2.txt; mv /tmp/windowlist2.txt /tmp/windowlist.txt
	# Use Yad to select window to "Remeber":
	selection=$(yad --class="IceWM-remember-settings" --name="list" --title=$"Add/Remove IceWM Window Defaults" \
--width=550 --height=400 --borders=20 --text=$"Select a program. Store it's window properties." \
--text-align=center --center --separator=" " --list  --column=$"What window configuration you want antiX to remember/forget?" \
--button=gtk-ok:0 --button=gtk-quit:1 < /tmp/windowlist.txt)
	#make the window the user selected the active one:
	wmctrl -R $selection
	# if nothing was selected simply exit
	[ -z "$selection" ] && loop=0 && echo "nothing was selected" && exit
}

main_dialog(){
	
	#restart data
	geo=
	x=
	y=
	left=
	top=
	class=
	layer=
	work=
	appname=
	appclass=
	
	# create temporary file
	temp=$(mktemp)
	
	# obtain window settings
	icesh $focus getGeometry getLayer getWorkspace \
		prop WM_CLASS prop _NET_FRAME_EXTENTS >"$temp"

	# file must have something
	if [[ ! -s $temp ]]
	then
		exit 1
	fi

	# remove punctuation
	sed -i -e 's|[+,]| |g' "$temp"

	# read values from file
	while read a b c d e f g h
	do
		if [[ $a =~ ^0x ]]
		then
			if [[ $b =~ ^WM_CLASS ]]
			then
				class=$d
			elif [[ $b =~ ^_NET_FRAME_EXTENTS ]]
			then
				left=$d
				top=$f
			elif [[ $b =~ ^[0-9]+$ || $b -eq -1 || $c = '"All"' ]]
			then
				work=$b
			elif [[ $b =~ ^[A-Z][a-z] ]]
			then
				layer=$b
			fi
		elif [[ $a =~ ^[0-9] ]]
		then
			geo=$a
			x=$b
			y=$c
		fi
	done <"$temp"
	
	# remove temporary file
	rm -f -- "$temp"
	
	#get more values:
	appclass=${class%.*} #delete last dot
	appname=${appclass%.*} #get window name
	appclass=${appclass#*.} #get window class
	appgeo="${geo}+${x}+${y}"

	# correct geometry
	let x-=$left
	let y-=$top

	cls_geo="${class}.geometry"
	new_geo="${cls_geo}: ${geo}+${x}+${y}"

	cls_lay="${class}.layer"
	new_lay="${cls_lay}: ${layer}"

	cls_wsp="${class}.workspace"
	new_wsp="${cls_wsp}: ${work}"
	
	#recreate temp file for yad script
	temp=$(mktemp)

	# main yad dialog
	yad --title=$"Add/Remove IceWM Window Defaults" --class="IceWM-remember-settings" --name="IceWM-remember-settings" \
		--text=$"Entries shown below are for the $appclass ($appname) window.\n\n\
All options marked will be saved, all unmarked will be deleted.\n\n \
Note: Workspace number shown is the window's current workspace. \n \
	Don't worry that it appears too low.\n\n" \
		--center --borders=20 --checklist --list --separator="" \
		--column=$"Select" --column="Entry" --column=$"Type" --column=$"Value" \
	true "geometry" $"Geometry" "$appgeo" \
	true "layer" $"Layer" "$layer" true $"workspace" "Workspace" "$work" >"$temp" \
		--hide-column=2 --print-column=2 --height=320 \
		--button=gtk-help:"bash -c help_dialog" --button=$"Select other":2 --button=gtk-ok:0 --button=gtk-quit:1 	
	
	##SELECTION MADE##
	exval=$?
		case $exval in
			0) save_changes;;
			2) select_window;;
			1) loop=0 ;;
			252) loop=0 ;;
		esac
	
	# remove temporary file
	rm -f -- "$temp"
}

###SCRIPT STARTS HERE###

#ready help window
export -f help_dialog
select_window
	
while [[ $loop -eq 1 ]]; do
    if [[ $select -eq 1 ]]
	then
		focus=
		main_dialog
	elif [[ $list -eq 1 ]]
	then
		focus="-f"
		list_dialog
		main_dialog
	else
		loop=0
		focus="-f"
		main_dialog
	fi
done

#clean extra yad windows
unset help_dialog