### Setup and Development for Ruby/Tk Source: https://github.com/ruby/tk/blob/master/README.md Steps for setting up the development environment for Ruby/Tk, including installing dependencies, running tests, and using the console. It also outlines the process for releasing a new version of the gem. ```bash bin/setup rake test bin/console bundle exec rake install bundle exec rake release ``` -------------------------------- ### Create Basic Ruby/Tk Application Source: https://context7.com/ruby/tk/llms.txt Demonstrates initializing a basic window with buttons and starting the Tk event loop to handle user interactions. ```ruby require 'tk' # Create buttons with event handlers TkButton.new(nil, :text => 'hello', :command => proc { print "hello\n" }).pack(:fill => 'x') TkButton.new(nil, :text => 'quit', :command => proc { exit }).pack(:fill => 'x') # Start the Tk event loop Tk.mainloop ``` -------------------------------- ### Install Ruby/Tk Gem Source: https://github.com/ruby/tk/blob/master/README.md Instructions for adding the Ruby/Tk gem to your project's Gemfile or installing it directly using the 'gem install' command. It also shows how to specify include and library paths for Tcl/Tk headers and libraries during installation. ```ruby gem 'tk' ``` ```bash $ bundle $ gem install tk $ gem install tk -- \ --with-tcl-include='/path/to/tcl/header/directory' \ --with-tk-include='/path/to/tk/header/directory' \ --with-tcl-lib='/path/to/tcl/shared/library/directory' \ --with-tk-lib='/path/to/tk/shared/library/directory' ``` -------------------------------- ### Install Ruby/Tk Gem Source: https://context7.com/ruby/tk/llms.txt Instructions for adding the tk gem to a project and configuring the necessary Tcl/Tk library paths for native compilation. ```ruby # Add to Gemfile gem 'tk' # Or install via command line with Tcl/Tk paths # gem install tk -- \ # --with-tcl-include='/path/to/tcl/header/directory' \ # --with-tk-include='/path/to/tk/header/directory' \ # --with-tcl-lib='/path/to/tcl/shared/library/directory' \ # --with-tk-lib='/path/to/tk/shared/library/directory' ``` -------------------------------- ### Tcl Interpreter Initialization (C) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code demonstrates initializing the Tcl interpreter and linking a C variable 'counter' to a Tcl variable. It includes necessary Tcl headers and uses Et_Init for application setup. The Et_AppInit function is called during initialization. ```c #include int counter = 0; int main(int argc, char **argv){ Et_Init(argc, argv); /*NOTREACHED*/ return 0; } int Et_AppInit(Tcl_Interp *interp){ if( Blt_Init(Interp) ){ return TCL_ERROR; } /* Example: Initialize an extension */ Tcl_LinkVar(interp, "counter", &counter, TCL_LINK_INT); /* Or link a C variable to a Tcl variable */ return TCL_OK; /* Return TCL_OK if successful */ } ``` -------------------------------- ### Display Standard Dialog Boxes Source: https://context7.com/ruby/tk/llms.txt Provides examples of common system dialogs including message boxes, file selection, color pickers, and directory choosers. ```ruby require 'tk' TkButton.new(nil, :text => 'Message Box', :command => proc { Tk.messageBox(:title => 'Information', :message => 'Operation completed successfully!', :type => 'ok', :icon => 'info') }).pack TkButton.new(nil, :text => 'Open File', :command => proc { filename = Tk.getOpenFile(:title => 'Select a file') puts "Selected: #{filename}" unless filename.empty? }).pack Tk.mainloop ``` -------------------------------- ### Tk Listbox Widget Operations Source: https://context7.com/ruby/tk/llms.txt Provides a comprehensive example of using the TkListbox widget in Ruby. It covers creating a listbox, setting its values, retrieving all items, getting selected indices, accessing specific items, performing selection operations (set, clear, check), clearing the listbox, getting its size, and integrating a scrollbar. ```ruby require 'tk' # Create a listbox listbox = TkListbox.new(nil, :height => 5, :width => 20) listbox.pack(:fill => 'both', :expand => true) # Set list values listbox.value = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'] # Get current value (all items) all_items = listbox.value # Get selected indices selected = listbox.curselection # Get item at specific index item = listbox.get(0) # Get first item items = listbox.get(0, 2) # Get items 0-2 # Selection operations listbox.selection_set(0, 2) # Select items 0-2 listbox.selection_clear(0, 'end') # Clear all selection is_selected = listbox.selection_includes(1) # Check if index 1 is selected # Clear the listbox listbox.clear # Get size count = listbox.size # Add scrollbar scrollbar = TkScrollbar.new listbox.configure(:yscrollcommand => proc { |*args| scrollbar.set(*args) }) scrollbar.configure(:command => proc { |*args| listbox.yview(*args) }) Tk.mainloop ``` -------------------------------- ### Implement C Command Module Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Example of adding a custom C function to a Tcl application, including argument parsing and result setting. ```c #include "hw.h" int ET_COMMAND_add(ET_TCLARGS){ int a, b; char zResult[30]; a = atoi(argv[1]); b = atoi(argv[2]); sprintf(zResult, "%d", a+b); Tcl_SetResult(interp, zResult, TCL_VOLATILE); return TCL_OK; } ``` -------------------------------- ### Add Double Quotes to Start of Each Line using Sed Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This 'sed' command prepends a double quote to the beginning of every line in a file. This is often used to format lines as string literals in programming or configuration contexts. ```bash sed -e 's/^/"/' \ ``` -------------------------------- ### Check Tcl_Init() Return Value for Errors Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code snippet shows how to properly use Tcl_Init() by checking its return value. If Tcl_Init() fails (returns non-TCL_OK), it prints an error message to stderr using Tcl_GetStringResult() to get the error details. ```c #include static char zInputLoop[] = /* Tcl code omitted... */ ; int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); if( Tcl_Init(interp)!=TCL_OK ){ fprintf(stderr,"Tcl_Init() failed: %s\n", Tcl_GetStringResult(interp)); } /* Print error message if Tcl_Init() fails */ /* Call Tcl_CreateCommand()? */ Tcl_Eval(interp, zInputLoop); return 0; } ``` -------------------------------- ### Tk Event Binding for Widgets Source: https://context7.com/ruby/tk/llms.txt Demonstrates how to bind keyboard and mouse events to Tk widgets in Ruby. It shows examples of binding mouse enter/leave events, button presses/releases, double-clicks to a label widget, and keyboard events (KeyPress, Return, Control-q) to the root window. ```ruby require 'tk' label = TkLabel.new(nil, :text => 'Hover or click me', :background => 'white', :relief => 'raised', :padx => 20, :pady => 20) label.pack(:padx => 10, :pady => 10) # Mouse events label.bind('Enter', proc { label.background = 'lightblue' }) label.bind('Leave', proc { label.background = 'white' }) label.bind('ButtonPress-1', proc { label.text = 'Pressed!' }) label.bind('ButtonRelease-1', proc { label.text = 'Released!' }) # Double-click label.bind('Double-1', proc { puts 'Double-clicked!' }) # Keyboard events (on root window) Tk.root.bind('KeyPress', proc { |e| puts "Key pressed: #{e.keysym}" }) Tk.root.bind('Return', proc { puts 'Enter key pressed' }) Tk.root.bind('Control-q', proc { exit }) ``` -------------------------------- ### Process Input Lines with Tcl for String Formatting Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This Tcl script reads lines from standard input, trims leading whitespace, skips empty lines and lines starting with '#', escapes backslashes and double quotes, and then prints each processed line as a Tcl string literal. ```tcl while {![eof stdin]} { set line [gets stdin] set line [string trimleft $line] if {$line==""} continue if {[string index $line 0]=="#"} { continue } regsub -all {\} $line {&&} line regsub -all {"} $line {\"} line puts "\"$line\\n\"" } ``` -------------------------------- ### Hello, World! with Tcl Library in C Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html A basic C program that initializes a Tcl interpreter, evaluates a Tcl command to print 'Hello, World!', and then exits. This demonstrates the fundamental steps of embedding Tcl. ```c #include int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_Eval(interp, "puts {Hello, World!}"); return 0; } ``` -------------------------------- ### Implement New Tcl Command in C Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Demonstrates creating a new Tcl command ('helloworld') by implementing it as a C function. This involves defining the C function signature, registering it with Tcl_CreateCommand, and evaluating Tcl code. ```c #include int NewCmd( void *clientData, Tcl_Interp *interp, int argc, char **argv ) { printf("Hello, World!\n"); return TCL_OK; } static char zInputLoop[] = /* Tcl code omitted... */ ; int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_CreateCommand(interp, "helloworld", NewCmd, 0, 0); Tcl_Eval(interp, zInputLoop); return 0; } ``` -------------------------------- ### Hello World Tk Application in C Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code defines the Tcl commands to create a button labeled 'Hello, World!' and pack it, along with the event loop and window destruction handler. It initializes Tcl and Tk interpreters and evaluates these commands. ```c #include static char zHello[] = "button .b " "-text {Hello, World} " "-command exit\n"; static char zEventLoop[] = "bind . {\n" " if {![winfo exists .]}\n" "}\n" "while 1 {vwait forever}\n"; int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_Init(interp); Tk_Init(interp); Tcl_Eval(interp, zHello); Tcl_Eval(interp, zEventLoop); /*NOTREACHED*/ } ``` -------------------------------- ### Custom Application Entry Point (C) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code provides a custom main function for the application. It calls Et_Init for application-specific initialization and is designed to never return, indicating it takes over program control. ```c int main(int argc, char **argv){ /* Application specific initialization */ Et_Init(argc, argv); /*NOTREACHED*/ return 0; } ``` -------------------------------- ### Delete Lines Starting with '#' using Sed Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This 'sed' command deletes lines from a file that begin with a '#' character, optionally preceded by spaces. This is useful for removing comments or configuration directives from script files. ```bash sed -e '/^ *#/d' \ ``` -------------------------------- ### Configure Toplevel Window Properties Source: https://context7.com/ruby/tk/llms.txt Shows how to control window attributes like title, geometry, and size constraints. It also demonstrates creating modal dialogs and handling the window close protocol. ```ruby require 'tk' root = Tk.root # Set window title root.title = 'My Application' # Set window size and position root.geometry('400x300+100+100') # Set minimum and maximum size root.minsize(200, 150) root.maxsize(800, 600) # Create additional toplevel window dialog = TkToplevel.new(root) { title 'Dialog Window' geometry '200x100' } # Make dialog modal (grab focus) dialog.grab_set # Close handler root.protocol('WM_DELETE_WINDOW', proc { result = Tk.messageBox(:message => 'Really quit?', :type => 'yesno') exit if result == 'yes' }) Tk.mainloop ``` -------------------------------- ### Implement TkLabel Widgets Source: https://context7.com/ruby/tk/llms.txt Shows how to create labels for static text, configure their appearance, and use TkVariable for dynamic text updates. ```ruby require 'tk' # Create a label with text label = TkLabel.new(nil, :text => 'Hello, World!') label.pack(:padx => 10, :pady => 10) # Configure label appearance label.configure(:foreground => 'blue', :font => 'Helvetica 18 bold') # Use a variable for dynamic text updates text_var = TkVariable.new('Initial text') dynamic_label = TkLabel.new(nil, :textvariable => text_var) dynamic_label.pack # Update label text dynamically text_var.value = 'Updated text' Tk.mainloop ``` -------------------------------- ### Implement TkText Widgets Source: https://context7.com/ruby/tk/llms.txt Shows how to create multi-line text editors, insert text at specific indices, retrieve content, and perform deletion operations. ```ruby require 'tk' # Create a text widget text = TkText.new(nil, :width => 40, :height => 10) text.pack(:fill => 'both', :expand => true) # Insert text at various positions text.insert('end', "Hello, World!\n") text.insert('1.0', "Start: ") # Insert at line 1, character 0 text.insert('end', "End of text") # Get text content content = text.get('1.0', 'end') # Get all text line = text.get('1.0', '1.end') # Get first line # Delete text text.delete('1.0', '1.5') # Delete first 5 characters ``` -------------------------------- ### Compile Tk Application on Unix Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This command compiles a C Tk application ('hello.c') on Unix-like systems using GCC. It links against the Tk, X11, and Tcl libraries, essential for GUI development. ```bash gcc hello.c -ltk -L/usr/X11R6/lib \ -lX11 -ltcl -lm -ldl ./a.out ``` -------------------------------- ### Schedule Tasks with Timers Source: https://context7.com/ruby/tk/llms.txt Demonstrates how to use the Tk.after method to schedule one-shot or repeating tasks in a GUI application. ```ruby require 'tk' label = TkLabel.new(nil, :text => 'Timer: 0') label.pack def update_timer(label, count) label.text = "Timer: #{count}" Tk.after(1000, proc { update_timer(label, count + 1) }) end update_timer(label, 0) Tk.mainloop ``` -------------------------------- ### Tcl Built-in Channel Type Definition (C) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code defines the 'builtin' Tcl channel type, specifying the procedures for closing, input, output, seeking, watching, and getting file handles for channels that read from built-in data. This structure is essential for Tcl_CreateChannel to manage custom file types. ```c static Tcl_ChannelType builtinChannelType = { "builtin", /* Type name. */ NULL, /* Always non-blocking.*/ BuiltinFileClose, /* Close proc. */ BuiltinFileInput, /* Input proc. */ BuiltinFileOutput, /* Output proc. */ BuiltinFileSeek, /* Seek proc. */ NULL, /* Set option proc. */ NULL, /* Get option proc. */ BuiltinFileWatch, /* Watch for events on console. */ BuiltinFileHandle, /* Get a handle from the device. */ }; ``` -------------------------------- ### Create Hello World Tcl Script Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html A basic Tcl script to create a button that exits the application when clicked. ```tcl button .b -text {Hello, World!} -command exit pack .b ``` -------------------------------- ### Mktclapp Command Line Usage Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Provides standard command-line instructions for generating the necessary header and source files for Mktclapp-based projects. ```bash mktclapp -header >appinit.h mktclapp -f appinit.mta >appinit.c mktclapp -help ``` -------------------------------- ### Building Tcl Library on Windows Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Steps to build the Tcl library (tcl82.lib and tcl82.dll) on Windows, involving obtaining necessary files, creating a definition file, and using dlltool to generate a static library. ```bash echo EXPORTS >tcl82.def nm tcl82.lib | grep 'T \_' | sed 's/. T //' >>tcl82.def dlltool --def tcl82.def --dllname tcl82.dll --output-lib libtcl82.a ``` -------------------------------- ### Tk Menu Widget for Application Menus Source: https://context7.com/ruby/tk/llms.txt Demonstrates the creation of menus and menu bars using the TkMenu widget in Ruby. It shows how to build a menu bar, add cascading menus (like File and Edit), include commands, separators, checkbuttons, and radiobuttons with associated variables. ```ruby require 'tk' root = Tk.root # Create menu bar menubar = TkMenu.new(root) root.configure(:menu => menubar) # File menu file_menu = TkMenu.new(menubar, :tearoff => false) menubar.add_cascade(:label => 'File', :menu => file_menu) file_menu.add_command(:label => 'New', :command => proc { puts 'New file' }) file_menu.add_command(:label => 'Open', :command => proc { puts 'Open file' }) file_menu.add_separator file_menu.add_command(:label => 'Exit', :command => proc { exit }) # Edit menu edit_menu = TkMenu.new(menubar, :tearoff => false) menubar.add_cascade(:label => 'Edit', :menu => edit_menu) edit_menu.add_command(:label => 'Cut') edit_menu.add_command(:label => 'Copy') edit_menu.add_command(:label => 'Paste') # Checkbutton and radiobutton menu items options_menu = TkMenu.new(menubar, :tearoff => false) menubar.add_cascade(:label => 'Options', :menu => options_menu) check_var = TkVariable.new(false) options_menu.add_checkbutton(:label => 'Enable Feature', :variable => check_var, :onvalue => true, :offvalue => false) radio_var = TkVariable.new('option1') options_menu.add_radiobutton(:label => 'Option 1', :variable => radio_var, :value => 'option1') options_menu.add_radiobutton(:label => 'Option 2', :variable => radio_var, :value => 'option2') Tk.mainloop ``` -------------------------------- ### Tcl Script for Default Initialization Sequence Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This Tcl script defines the default behavior for initializing the Tcl environment. It computes tcl_libPath, searches for init.tcl in various locations, sources it, and handles potential errors during the process. It's designed to be executed by Tcl_Init(). ```tcl set errors {} set dirs {} if {[info exists tcl_library]} { lappend dirs $tcl_library } else { if {[info exists env(TCL_LIBRARY)]} { lappend dirs $env(TCL_LIBRARY) } lappend dirs $tclDefaultLibrary unset tclDefaultLibrary set dirs [concat $dirs $tcl_libPath] } foreach i $dirs { set tcl_library $i set tclfile [file join $i init.tcl] if {[file exists $tclfile]} { if {! [catch {uplevel #0 [list source $tclfile]} msg]} { return } else { append errors "$tclfile: $msg\n$errorInfo\n" } } } error "Can't find a usable init.tcl ..." ``` -------------------------------- ### Tcl Initialization Scripts Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Explains the concept of Tcl initialization scripts, which are used to load essential Tcl procedures and commands (like 'parray') during interpreter startup. These scripts are stored in the Tcl Library directory. ```text Initialization scripts load commands like 'parray'. These scripts reside in the 'Tcl Library' directory. They are essential for the initial setup of the Tcl interpreter. ``` -------------------------------- ### Compiling C with Tcl Library (Unix) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Demonstrates how to compile a C program that embeds Tcl on Unix-like systems. It shows direct linking with the static Tcl library and using the -L and -ltcl flags. ```bash gcc hello.c -ltcl -lm -ldl ./a.out ``` ```bash gcc -I../tcl8.2.2/generic hello.c \ ../tcl8.2.2/unix/libtcl8.2.a -lm -ldl strip a.out ./a.out ``` ```bash gcc -I../tcl8.2.2/generic hello.c \ -L../tcl8.2.2/unix -ltcl -lm -ldl strip a.out ./a.out ``` -------------------------------- ### Implement TkFrame Containers Source: https://context7.com/ruby/tk/llms.txt Explains how to use frames to organize widgets, create nested layouts, and define custom frame classes. ```ruby require 'tk' # Create a frame with border frame = TkFrame.new(nil, :relief => 'raised', :borderwidth => 2) frame.pack(:fill => 'both', :expand => true, :padx => 10, :pady => 10) # Add widgets to the frame TkLabel.new(frame, :text => 'Inside frame').pack TkButton.new(frame, :text => 'Frame button').pack # Nested frames for complex layouts top_frame = TkFrame.new(nil, :relief => 'groove', :borderwidth => 1) top_frame.pack(:fill => 'x') bottom_frame = TkFrame.new(nil, :relief => 'sunken', :borderwidth => 1) bottom_frame.pack(:fill => 'both', :expand => true) # Create a custom frame class class MyFrame < TkFrame def initialize(parent = nil) super(parent, :classname => 'MyFrame') # Add child widgets here end end Tk.mainloop ``` -------------------------------- ### Implement TkEntry Widgets Source: https://context7.com/ruby/tk/llms.txt Demonstrates single-line text entry, including inserting/deleting text, managing selection ranges, cursor positioning, and variable binding. ```ruby require 'tk' # Create an entry widget entry = TkEntry.new(nil, :width => 30) entry.pack(:padx => 10, :pady => 10) # Insert text at a position entry.insert(0, 'Default text') # Get the current value current_value = entry.value puts "Entry value: #{current_value}" # Set a new value entry.value = 'New value' # Delete text (from position 0 to end) entry.delete(0, 'end') # Selection operations entry.selection_range(0, 5) # Select characters 0-5 entry.selection_clear # Clear selection selected = entry.selection_present # Check if selection exists # Cursor position entry.cursor = 10 # Set cursor position pos = entry.cursor # Get cursor position # Bind entry to a variable text_var = TkVariable.new bound_entry = TkEntry.new(nil, :textvariable => text_var) bound_entry.pack Tk.mainloop ``` -------------------------------- ### Create Tk Interface and Button in Ruby Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This snippet demonstrates how to create a simple Tk interface with a button labeled 'Hello' that exits the application when clicked. It then packs the button to make it visible. ```ruby button .b -text Hello -command exit pack .b ``` -------------------------------- ### Manage Widget Layouts with Pack, Grid, and Place Source: https://context7.com/ruby/tk/llms.txt Illustrates the three primary geometry managers in Tk: pack for simple stacking, grid for tabular layouts, and place for absolute or relative positioning. ```ruby require 'tk' # Pack frame1 = TkFrame.new { pack(:side => 'top', :fill => 'x') } TkButton.new(frame1, :text => 'Left').pack(:side => 'left') # Grid frame2 = TkFrame.new { pack(:fill => 'both', :expand => true) } TkLabel.new(frame2, :text => 'Name:').grid(:row => 0, :column => 0) TkEntry.new(frame2).grid(:row => 0, :column => 1) # Place frame3 = TkFrame.new(:width => 200, :height => 100) frame3.pack TkButton.new(frame3, :text => 'Placed').place(:x => 50, :y => 25) Tk.mainloop ``` -------------------------------- ### Implement TkButton Widgets Source: https://context7.com/ruby/tk/llms.txt Covers creating buttons with command callbacks using procs or blocks, and utilizing built-in button methods like invoke and flash. ```ruby require 'tk' # Button with command callback using proc button = TkButton.new(nil, :text => 'Click Me', :command => proc { puts 'Button clicked!' }) button.pack(:padx => 20, :pady => 20) # Button with block syntax TkButton.new(nil, :text => 'Exit') { command proc { exit } pack(:fill => :x, :expand => true) } # Button methods button.invoke # Programmatically invoke the button button.flash # Flash the button momentarily Tk.mainloop ``` -------------------------------- ### Building a Simple TCLSH in C Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code implements a basic command-line interpreter similar to TCLSH. It reads lines from standard input, evaluates them using the Tcl interpreter, and prints the results. It includes basic error handling for Tcl evaluation. ```c #include int main(int argc, char **argv){ Tcl_Interp *interp; char *z; char zLine[2000]; interp = Tcl_CreateInterp(); while( fgets(zLine,sizeof(zLine),stdin) ){ /* Get one line of input */ Tcl_Eval(interp, zLine); /* Execute the input as Tcl. */ z = Tcl_GetStringResult(interp); if( z[0] ){ printf("%%s\n", z); } /* Print result if not empty */ } return 0; } ``` -------------------------------- ### Create Tcl Command with Tcl_Obj Interface in C Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Demonstrates the Tcl_Obj interface for creating Tcl commands in C, which uses Tcl_Obj pointers for arguments and is generally more efficient for complex data types. ```c int NewObjCmd( void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const* objv ) { /* Implementation... */ return TCL_OK; } static char zInputLoop[] = /* Tcl code omitted... */ ; int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_CreateObjCommand(interp, "newcmd", ``` -------------------------------- ### Compile Tk Application on Windows (Mingw32) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This command compiles a C Tk application on Windows using Mingw32's GCC. It uses '-mno-cygwin' for a native Windows executable and links against specific Tk/Tcl library versions. ```bash gcc -mno-cygwin hello.c -mwindows \ -ltk82 -ltcl82 -lm a.exe ``` -------------------------------- ### Return Success from C to Tcl Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Shows how a C function implementing a Tcl command should return an integer status, typically TCL_OK, to indicate successful execution. ```c int NewCmd(TCLARGS){ return TCL_OK; } ``` -------------------------------- ### Compile Tk Application on Windows (Cygwin) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This command compiles a C Tk application on Windows using Cygwin's GCC. The '-mwindows' flag creates a Windows-style application, and specific Tk/Tcl library versions are linked. ```bash gcc hello.c -mwindows -ltk80 -ltcl80 -lm a.exe ``` -------------------------------- ### Basic C Program with Tcl Integration Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html A simple C program that initializes a Tcl interpreter. It serves as a basic structure for embedding Tcl code within a C application. The placeholder comment indicates where application-specific Tcl logic would be inserted. ```c #include int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); /* Your application code goes here */ return 0; } ``` -------------------------------- ### Compiling C with Tcl Library (Windows) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Provides compilation commands for embedding Tcl in C applications on Windows using Cygwin and MinGW32 toolchains. ```bash gcc hello.c -ltcl80 -lm a.exe ``` ```bash gcc -mno-cygwin hello.c -ltcl82 -lm ``` -------------------------------- ### Compile mktclapp Tool Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This command compiles the 'mktclapp.c' utility using a C compiler. This tool is used to mix C/C++ with Tcl/Tk into a standalone binary. ```bash cc -o mktclapp mktclapp.c ``` -------------------------------- ### Tcl Script for Better Command-Line Input Handling Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This Tcl script provides improved handling for command-line input, allowing commands to span multiple lines. It prompts the user, appends input until a complete command is detected, and then executes it using 'uplevel #0'. Error handling is included. ```tcl set line {} while {! [eof stdin]} { if {$line!=""} { puts -nonewline "> " } else { puts -nonewline "% " } flush stdout /* Prompt for user input. The prompt is normally " but changes to ">" if the current line is a continuation. */ append line [gets stdin] if {[info complete $line]} { if {[catch {uplevel #0 $line} result]} { /* If the command is complete, execute it. */ puts stderr "Error: $result" } elseif {$result!=""} { puts $result } set line {} } else { append line \n } /* If the command is incomplete, append a newline and get another line of text. */ } ``` -------------------------------- ### Implementing Custom File Channel with TclOpenFileChannelInsertProc (C) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code defines the BuiltinFileOpen function, which is registered via TclOpenFileChannelInsertProc. It handles opening 'built-in' files by creating a Tcl channel that reads from compiled-in data. This is crucial for embedding scripts and resources directly into an executable. ```c static Tcl_Channel BuiltinFileOpen( Tcl_Interp *interp, /* The TCL interpreter doing the open */ char *zFilename, /* Name of the file to open */ char *modeString, /* Mode string for the open (ignored) */ int permissions /* Permissions for a newly created file (ignored) */ ){ char *zData; BuiltinFileStruct *p; int nData; char zName[50]; Tcl_Channel chan; static int count = 1; zData = FindBuiltinFile(zFilename, 1, &nData); if( zData==0 ) return NULL; p = (BuiltinFileStruct*)Tcl_Alloc( sizeof(BuiltinFileStruct) ); if( p==0 ) return NULL; p->zData = zData; p->nData = nData; p->cursor = 0; sprintf(zName,"etbi_bffffc7c_8049b04",((int)BuiltinFileOpen)>>12,count++); chan = Tcl_CreateChannel(&builtinChannelType, zName, (ClientData)p, TCL_READABLE); return chan; } ``` -------------------------------- ### Invoking Tcl Commands from C with Et_EvalF Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Demonstrates how to safely execute Tcl commands from C code using Et_EvalF. It highlights the importance of using the % format specifier to properly escape special characters in Tcl strings. ```C #include "appinit.h" void ErrMsg(char *zMsg){ Et_EvalF(Et_Interp, "tk_messageBox -icon error -msg \"%\" -type ok", zMsg); } ``` -------------------------------- ### Tcl Object Interface Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Highlights the Tcl_Obj interface as the recommended way to interact with Tcl data, emphasizing its performance benefits and suitability for new Tcl extensions. It notes that the benefits are less pronounced when mixing C/C++ with Tcl/Tk. ```text Use the Tcl_Obj interface for new Tcl extensions. Access methods for Tcl_Objs are crucial. Benefits include speed and binary data handling, though C/C++ may still be faster for binary data. ``` -------------------------------- ### Implement Tcl_Obj Interface Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Using the Tcl_Obj interface for higher performance when handling command arguments and results. ```c #include "hw.h" int ET_OBJCOMMAND_add2(ET_OBJARGS){ int a, b; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "number number"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &a) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR; Tcl_SetIntObj(Tcl_GetObjResult(interp), a+b); return TCL_OK; } ``` -------------------------------- ### Invoke Tcl_Init() to Initialize Tcl Interpreter Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code snippet demonstrates the basic usage of Tcl_Init() to initialize a Tcl interpreter. It creates an interpreter, calls Tcl_Init() to load initialization scripts, and then evaluates a Tcl string. It does not include error handling for Tcl_Init(). ```c #include static char zInputLoop[] = /* Tcl code omitted... */ ; int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_Init(interp); /* Call Tcl_CreateCommand()? */ Tcl_Eval(interp, zInputLoop); return 0; } ``` -------------------------------- ### C Program to Execute Tcl Input Handling Script Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html A C program that initializes a Tcl interpreter and then executes an external Tcl script named 'input.tcl'. This script contains the logic for handling multi-line commands entered by the user. ```c #include int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_Eval(interp, "source input.tcl"); /* Read and execute the input loop */ return 0; } ``` -------------------------------- ### Tcl Dynamically Resizable Strings Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Offers functions for managing dynamically resizable strings (DStrings) in Tcl. These functions allow for efficient string building and manipulation, including appending elements, initializing, and retrieving string values. ```c Tcl_DStringAppend Tcl_DStringAppendElement Tcl_DStringEndSublist Tcl_DStringInit Tcl_DStringLength Tcl_DStringResult Tcl_DStringSetLength Tcl_DStringStartSublist Tcl_DStringValue ``` -------------------------------- ### Converting Tcl Scripts to Strings using SED Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This command shows how to use the 'sed' utility to convert Tcl scripts into C-style strings. It specifically handles escaping backslashes by replacing single backslashes with double backslashes. ```bash sed -e 's/\\/\\\\/g' \ ``` -------------------------------- ### Redefine 'source' Command for Standalone Initialization Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code demonstrates redefining the 'source' command in Tcl to enable standalone initialization. It intercepts calls to 'source', serving built-in scripts like init.tcl and parray.tcl directly from C strings. If a script is not built-in, it falls back to Tcl_EvalFile(). ```c static char zInitTcl[] = "..."; static char zParrayTcl[] = "..."; int NewSourceCmd(TCLARGS){ if( !strcmp(argv[1],"/builtin/init.tcl") ) return Tcl_Eval(interp, zInitTcl); if( !strcmp(argv[1],"/builtin/parray.tcl") ) return Tcl_Eval(interp, zParrayTcl); /* Call Tcl_Eval() on builtin strings if the names match */ return Tcl_EvalFile(interp, argv[1]); /* Call Tcl_EvalFile() if no match */ } int main(int argc, char **argv){ Tcl_Interp *interp; setenv("TCL_LIBRARY","/builtin"); /* Causes tclInit to look for init.tcl in /builtin */ interp = Tcl_CreateInterp(); Tcl_CreateCommand(interp, "source", NewSourceCmd, 0, 0); /* Redefine source */ Tcl_Init(interp); Tcl_Eval(interp, zInputLoop); return 0; } ``` -------------------------------- ### Tk Text Widget Tag Operations and Event Binding Source: https://context7.com/ruby/tk/llms.txt Demonstrates how to configure tags for text styling (background, foreground) and apply them to specific ranges within a Tkinter text widget. It also shows how to bind mouse events to these tags and perform text searches. ```ruby require 'tk' # Create a text widget (assuming 'text' is already defined) # For demonstration, let's create one: root = Tk.root text = TkText.new(root) text.pack # Tag operations for styling text.tag_configure('highlight', :background => 'yellow', :foreground => 'black') text.tag_add('highlight', '1.0', '1.10') # Apply tag to range # Search text pos = text.search('World', '1.0') # Bind events to tags text.tag_bind('highlight', 'Enter', proc { puts 'Mouse entered highlight' }) Tk.mainloop ``` -------------------------------- ### Set Result from C to Tcl Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Illustrates how to set a result string from a C function back to Tcl using Tcl_SetResult, which is then available to the Tcl interpreter. ```c int NewCmd(TCLARGS){ Tcl_SetResult(interp,"Hello!",TCL_STATIC); return TCL_OK; } ``` -------------------------------- ### Tcl Input Loop for Unlimited Input Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This Tcl script defines a loop to handle input lines of unlimited length. It reads lines from stdin, evaluates them using 'eval', and prints the results. This approach is more robust than fixed-size buffers. ```tcl while {! [eof stdin]} { set line [gets stdin] /* Get one line of input */ set result [eval $line] /* Execute input as Tcl */ if {$result!=""} {puts $result} /* Print result */ } ``` -------------------------------- ### Custom Event Loop Implementation (C) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code shows how to implement a custom event loop for Tcl applications. It replaces the default event loop with Et_CustomMainLoop, allowing for intermixed processing and event handling. The main function initializes Tcl and then calls the custom loop. ```c #include void Et_CustomMainLoop(Tcl_Interp *interp){ for(;;){ Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT); /* Other processing... */ } /* Intermix processing and event handling */ } int main(int argc, char **argv){ Et_Init(argc, argv); /* Never returns */ /*NOTREACHED*/ return 0; } ``` -------------------------------- ### Format Lines as Tcl String Literals using Sed Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This 'sed' command formats lines by adding leading spaces and a double quote at the beginning, and a newline character followed by a double quote at the end. This prepares lines to be part of a multi-line Tcl string literal. ```bash sed -e 's/^ */ "/' \ -e 's/$/\\n"/' input.tcl ``` -------------------------------- ### Validate C Command Parameters Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Enhanced C implementation that validates the number of arguments and ensures they are integers. ```c #include "hw.h" int ET_COMMAND_add(ET_TCLARGS){ int a, b; char zResult[30]; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be: \"", argv[0], " VALUE VALUE\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &a)!=TCL_OK ) return TCL_ERROR; if( Tcl_GetInt(interp, argv[2], &b)!=TCL_OK ) return TCL_ERROR; sprintf(zResult, "%d", a+b); Tcl_SetResult(interp, zResult, TCL_VOLATILE); return TCL_OK; } ``` -------------------------------- ### Compile Mktclapp Generated C Code Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Commands to compile the generated C code into an executable on different platforms. ```bash cc hw.c -ltk -L/usr/X11R6/lib -lX11 -ltcl -lm -ldl gcc hw.c -mwindows -ltk80 -ltcl80 -lm gcc -mno-cygwin hw.c -mwindows -ltk82 -ltcl82 -lm ``` -------------------------------- ### Compiling Tcl Scripts into C Programs Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code demonstrates how to compile Tcl scripts into C programs. It includes a Tcl script embedded as a C string and then evaluates it using the Tcl interpreter. The actual Tcl code is omitted but represented by a placeholder. ```c #include static char zInputLoop[] = /* Actual code omitted */ ; int main(int argc, char **argv){ Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_Eval(interp, zInputLoop); /* Execute the Tcl code */ return 0; } ``` -------------------------------- ### Define Custom Tcl Command in Namespace (C) Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html This C code defines a new Tcl command 'adder::add' within a namespace. It handles argument validation, integer conversion, and returns the sum of two integers. It requires the Tcl library and uses Tcl error handling. ```c #include int ET_COMMAND_adder__add(ET_TCLARGS){ int a, b; char *zResult[30]; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be: "", argv[0], " VALUE VALUE\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &a)!=TCL_OK ){ return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &b)!=TCL_OK ){ return TCL_ERROR; } sprintf(zResult, "%d", a+b); Tcl_SetResult(interp, zResult, TCL_VOLATILE); return TCL_OK; } ``` -------------------------------- ### Manage Tk Event Loop and Timers Source: https://context7.com/ruby/tk/llms.txt Demonstrates how to cancel scheduled timers using Tk.after_cancel and register idle callbacks with Tk.after_idle. These methods are essential for managing background tasks and event loop responsiveness. ```ruby require 'tk' # Cancel a scheduled timer # Tk.after_cancel(after_id) # Idle callback (runs when event loop is idle) Tk.after_idle(proc { puts 'Event loop is idle' }) Tk.mainloop ``` -------------------------------- ### Define Tcl Command Arguments Macro in C Source: https://github.com/ruby/tk/blob/master/sample/tkextlib/tkHTML/page3/index.html Introduces a C macro 'TCLARGS' as a shortcut for defining the standard four parameters required for Tcl command functions, simplifying function definitions. ```c #define TCLARGS \ void *clientData, \ Tcl_Interp *interp, \ int argc, \ char *argv int NewCmd(TCLARGS){ /* implementation...*/ } ```