#!/bin/ksh # # Draw a fractal with the GTK-server and KornShell. # # All right, so it is not fast. All right, it is useless. # So why did I create it? Just to see if it was possible. # That's all. # # On my AMD2000+ machine it takes approx. 7 minutes to # draw the fractal. # # Developed with ksh (AT&T Korn Shell 93) on Slackware Linux. # Does NOT work with PDKSH. # # Codesample. July 25, 2005 - PvE. # Changed to embedded GTK at October 8, 2006 # Improved at december 20, 2006 #------------------------------------------------------- GTK stuff # Create embedded GTK functions if [[ ! -f /etc/gtk-server.cfg ]] then print "No GTK-server configfile found! Please install GTK-server..." exit 1 elif [[ ! -f $HOME/.gtk4korn || /etc/gtk-server.cfg -nt $HOME/.gtk4korn ]] then print "# Embedded GTK functions for KornShell" > $HOME/.gtk4korn while read LINE do if [[ $LINE == +(*FUNCTION_NAME*) ]] then TMP=${LINE#*= } print "function ${TMP%%,*}" >> $HOME/.gtk4korn print "{\nprint -p ${TMP%%,*} \$@" >> $HOME/.gtk4korn print "read -p GTK\n}" >> $HOME/.gtk4korn fi done < /etc/gtk-server.cfg fi NULL="NULL" # Include embedded GTK for KornShell . $HOME/.gtk4korn #------------------------------------------------------- # The core calculation routine was taken from # http://www.cygnus-software.com/theory/theory.htm # and translated to KornShell by me. # With friendly permission of Cygnus-Software. function Draw_Fractal { integer MaxIters=100 integer SIZE=240 integer BLACK=-1 typeset -F LEFT=-2.0 RIGHT=1.0 typeset -F TOP=1.0 BOTTOM=-1.0 typeset -F ZR ZI CR CI RSQUARED ISQUARED typeset -i INDEX # Tell drawing is starting gdk_color_parse "#000000" $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR gdk_draw_layout $PIX $GC 10 240 $START gtk_widget_queue_draw $IMAGE gtk_server_callback "update" # The calculation integer Y=0 while [[ $Y -lt $SIZE ]] do integer X=0 while [[ $X -lt $SIZE ]] do ZR=0.0 ZI=0.0 let CR=$LEFT+$X*($RIGHT-1*$LEFT)/$SIZE let CI=$TOP+$Y*($BOTTOM-$TOP)/$SIZE let RSQUARED=$ZR*$ZR let ISQUARED=$ZI*$ZI integer COUNT=0 while [[ $RSQUARED+$ISQUARED -lt 2.0 && $COUNT -lt $MaxIters ]] do let ZI=$ZR*$ZI*2.0 let ZI=$ZI+$CI let ZR=$RSQUARED-$ISQUARED let ZR=$ZR+$CR let RSQUARED=$ZR*$ZR let ISQUARED=$ZI*$ZI ((COUNT+=1)) done let SUM=$RSQUARED+$ISQUARED if [[ $SUM -lt 2.0 ]] then if [[ $SUM -lt 1.0 ]] then let INDEX=$SUM*16 else INDEX=15 fi gdk_color_parse ${PICOL[$INDEX]} $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR gdk_draw_point $PIX $GC $X $Y gtk_server_callback "update" if [[ $GTK = $EXIT_BUTTON || $GTK = $WIN ]] then gtk_exit 0 exit fi fi ((X+=1)) done gtk_widget_queue_draw $IMAGE gtk_server_callback "update" ((Y+=1)) done # Wipe wait text gdk_color_parse "#ffffff" $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR gdk_draw_rectangle $PIX $GC 1 10 240 120 25 # Tell drawing is ready gdk_color_parse "#000000" $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR gdk_draw_layout $PIX $GC 10 240 $READY gtk_widget_queue_draw $IMAGE gtk_server_callback "update" } #------------------------------------------------------- # Setup environment for GTK server export LC_ALL=C export LD_LIBRARY_PATH=/usr/X11R6/lib # Define array with colors - taken from the # newLisp HTML fractal example PICOL[0]="#800000" PICOL[1]="#800080" PICOL[2]="#8000FF" PICOL[3]="#808000" PICOL[4]="#808080" PICOL[5]="#8080FF" PICOL[6]="#80FF00" PICOL[7]="#80FF80" PICOL[8]="#80FFFF" PICOL[9]="#FF0000" PICOL[10]="#FF0080" PICOL[11]="#FF00FF" PICOL[12]="#FF8000" PICOL[13]="#FF8080" PICOL[14]="#FF80FF" PICOL[15]="#FFFF00" # Start GTK-server in STDIN mode gtk-server stdin |& # Check GTK version gtk_check_version 2 4 0 if [[ -n $GTK ]] then echo "Your GTK installation is too old!" echo "GTK version 2.4.0 or higher is required. Exiting..." gtk_exit 0 exit 1 fi # Window gtk_init $NULL $NULL gtk_window_new 0 WIN=$GTK gtk_window_set_title $WIN "'KornShell with GTK-server'" gtk_widget_set_size_request $WIN 300 300 gtk_window_set_position $WIN 1 gtk_window_set_resizable $WIN 0 # Create widget to display image gtk_image_new IMAGE=$GTK # Create eventbox to catch mouseclick gtk_event_box_new EBOX=$GTK gtk_container_add $EBOX $IMAGE # Separator gtk_hseparator_new SEP=$GTK # Action button gtk_button_new_with_label "Draw!" ACTION_BUTTON=$GTK gtk_widget_set_size_request $ACTION_BUTTON 75 30 # Clear button gtk_button_new_with_label "Clear" CLEAR_BUTTON=$GTK gtk_widget_set_size_request $CLEAR_BUTTON 75 30 # Exit button gtk_button_new_with_label "Exit" EXIT_BUTTON=$GTK gtk_widget_set_size_request $EXIT_BUTTON 75 30 # Now arrange widgets on window using boxes gtk_hbox_new 0 0 HBOX=$GTK gtk_box_pack_start $HBOX $CLEAR_BUTTON 0 0 1 gtk_box_pack_start $HBOX $ACTION_BUTTON 0 0 1 gtk_box_pack_end $HBOX $EXIT_BUTTON 0 0 1 gtk_vbox_new 0 0 VBOX=$GTK gtk_box_pack_start $VBOX $EBOX 0 0 1 gtk_box_pack_start $VBOX $SEP 0 0 1 gtk_box_pack_end $VBOX $HBOX 0 0 1 gtk_container_add $WIN $VBOX # Show all widgets gtk_widget_show_all $WIN # Create the pixmap gtk_widget_get_parent_window $IMAGE GDKWIN=$GTK gdk_pixmap_new $GDKWIN 300 265 -1 PIX=$GTK gdk_gc_new $PIX GC=$GTK gtk_image_set_from_pixmap $IMAGE $PIX $NULL # Allocate memory with some random widget for GdkColor gtk_frame_new $NULL COLOR=$GTK # Now set foreground and backgroundcolors to WHITE gdk_color_parse "#ffffff" $COLOR gdk_gc_set_rgb_bg_color $GC $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR # Clear the complete pixmap with WHITE gdk_draw_rectangle $PIX $GC 1 0 0 300 265 # Set color to BLACK gdk_color_parse "#000000" $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR # Put some text on the canvas gtk_widget_create_pango_layout $IMAGE "'Draw a fractal with Korn!'" LAYOUT=$GTK gdk_draw_layout $PIX $GC 130 240 $LAYOUT # Define start and finishing text gtk_widget_create_pango_layout $IMAGE "'Please wait...'" START=$GTK gtk_widget_create_pango_layout $IMAGE "'Drawing ready.'" READY=$GTK # Update the IMAGE widget with the pixmap gtk_widget_queue_draw $IMAGE # Mainloop while [[ $GTK != $WIN && $GTK != $EXIT_BUTTON ]] do # Get event gtk_server_callback "wait" # Check events case $GTK in # If action button is pressed $ACTION_BUTTON) Draw_Fractal;; # If clear button is pressed $CLEAR_BUTTON) gdk_color_parse "#ffffff" $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR gdk_draw_rectangle $PIX $GC 1 0 0 450 265 gdk_color_parse "#000000" $COLOR gdk_gc_set_rgb_fg_color $GC $COLOR gdk_draw_layout $PIX $GC 130 240 $LAYOUT gtk_widget_queue_draw $IMAGE;; esac done # Exit GTK gtk_exit 0