#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"
package require -exact Gnocl 3.24
set str "\tAbc def ghi klm a. \tYes! "
## reduce multiple spaces within a string but retain \t, trim all external spaces.
# args: str string to modify
# returns: updated string
#
proc removeSpaces { str } {
while 1 {
if { [string first " " $str] == -1 } { break }
set str [string map [list " " " "] $str]
}
return [string trim $str " "]
}
puts >[removeSpaces $str]<
Saturday, November 02, 2024
Remove Stray Repeated Spaces from a String
Friday, October 25, 2024
Search for Named Icons
#
# return a sorted list of available icons with a name matching search pattern
#
proc findIcon {pattern} {
# load list of available icons
set contexts [gnocl::icon contexts]
foreach context $contexts {
lappend ICONS $context [lsort [gnocl::icon icons -context $context]]
}
foreach {k v} $ICONS {
foreach i [lsearch -all -glob $v $pattern ] {
lappend res [lindex $v $i]
}
}
return [lsort $res]
}
Sunday, September 29, 2024
Simple Tcl/Gnocl based widget message bar.
The gtk api provides it own status bar widget which could be used for embedded widget feedback but this it aimed at being used as part of a application's toplevel window.
A complex UI may have several component zone each of which giving its own feedback. This simpler messaging areas provided this capability by making feedback available by directly displaying the contents of global variables rather than pushing items onto a status message stack.
if 0 {
+-------------------------------------------------------------------------+
| msg0 | msg1 | msg2 | msg3 |
+-------------------------------------------------------------------------+
}
##
# Simple Tcl/Gnocl based message bar
# ref = unique ref (could be uapp or parent widget-id}
# itesm = list of extra field to be displayed in var val tooltip
# args = options to be passed to container
proc gnocl::messageBar { {ref myapp} {values { {A a Z} {B b Y} {C c X} }} args} {
set bar [gnocl::hBox {*}$args]
$bar add [gnocl::label \
-baseFont {Sans 9} \
-text msg0 \
-variable ${ref}(msg) ] -align left -expand 1
foreach item $values {
lassign $item i j k
set ::${ref}($i) $j
$bar add [gnocl::label \
-baseFont {Sans 9} \
-variable ${ref}($i) \
-widthChars 5 \
-align center \
-tooltip $k] -padding 10
}
return $bar
}
set container [gnocl::vBox]
set txt [gnocl::text -useMarkup 1]
$container add $txt -fill 1 -expand 1
$container add [gnocl::messageBar myapp [list {A a Z} {B b Y} {C c X} {D d W} {E e V} {F f}] -tooltip Messages] -align left
$txt verse 4
gnocl::window -child $container -width 500 -height 500
set myapp(msg) "Ok, ready to edit!"
parray myapp
Sunday, September 08, 2024
Using GnoclOption functions to Return Values for Customised Widget Options.
What to do...
Make changes to the widgetFunc function to enable the GnoclOption function for that option to return a value by setting the ret to point ot a TclObj.
/* this is a gnocl option handler ?? */
case GNOCL_CGET_NOTHANDLED: {
/* cget for gnocl options handled in option function
* the caveat here is that different widgets with the same option name may act differently,
* if this is the case, then would it be more practical to create specific option functions?
* (08/09/25)
*/
Tcl_Obj *ret = NULL;
options[idx2].func ( interp, &options[idx2], G_OBJECT ( area ), &ret );
Tcl_SetObjResult (interp, ret);
}
Wednesday, August 07, 2024
Dynamic Allocation of an Array of Strings in C.
https://www.geeksforgeeks.org/how-to-create-a-dynamic-array-of-strings-in-c/
In C, dynamic arrays are essential for handling data structures whose size changes dynamically during the program’s runtime. Strings are arrays of characters terminated by the null character ‘\0’. A dynamic array of strings will ensure to change it’s size dynamically during the runtime of the program as per the user’s needs. In this article, we will learn how to create a dynamic array of strings in C.
Create a Dynamic Array of Strings in C
To create a dynamic array of strings in C, we can use the concept of double pointer and dynamic memory allocation. The double pointer is the pointer that stores the memory address of another pointer. We create an array of pointers to characters (i.e. strings) and then store the address of this array in the double-pointer to characters. Each of the pointer to the character is again allocated memory based on the size of the string it is storing.
Approach
- Initialize a double pointer to store an array of strings.
- Allocate memory for the initial size of the array using the malloc function.
- Each element in the array will be a pointer to a string.
- For each pointer in the array, allocate memory for the string using the malloc function.
- Use the sprintf function to assign value to the string in the array.
- Free memory for each string using the free function.
- Free memory for the whole array of pointers using the free function.
Note: We have to first free() the memory allocated to each of the pointer of the array and then free the array of pointers. Otherwise, it may lead to the memory leak.
C Program to Create a Dynamic Array of Strings
The following program illustrates how to create a dynamic array of strings in C:
// C Program to illustrate how to create a dynamic array of
// strings
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// define the maximum length of the string you will store in
// the array
#define MAX_STRING_LENGTH 20
int main()
{
// Initialize a double pointer to store the array of
// strings
char** strings = NULL;
// Declare the initial size of the dynamic array
int size = 5;
// Allocate memory for the array of strings
strings = (char**)malloc(size * sizeof(char*));
if (strings == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return 1;
}
// Allocate memory for each string and assign values
for (int i = 0; i < size; i++) {
// Allocate memory for each string
strings[i] = (char*)malloc((MAX_STRING_LENGTH + 1)
* sizeof(char));
if (strings[i] == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return 1;
}
// Assign values to each string
sprintf(strings[i], "Student%d", i);
}
// Print the strings present in the array
for (int i = 0; i < size; i++) {
printf("%s\n", strings[i]);
}
// Free memory for each string
for (int i = 0; i < size; i++) {
free(strings[i]);
}
// Free memory for the array of pointers
free(strings);
return 0;
}
Monday, July 15, 2024
Overhaul of widget cget functionality.
The current basis of the cget function for widgets is based upon code written over 20yrs ago and, whilst it works reasonably well for the simple setting of gtk widget properties, support for more complex custom options is hit and miss.
const char *optName;
enum GnoclOptionType type;
const char *propName;
gnoclOptFunc *func;
const char *description;
const char *values;
With the recent updating of the C sources which includes an expansion of the GnoclOption structure to accommodate documentation support, it well worth reviewing the way in which widget functions handle the return of options.
Rather than treating the retrieval of properties set by a function as the final call, perhaps it should be prioritized. If one is not present, then extract a value based upon the setting type.
case CgetIdx: {
int idx;
/* get the idx of the option in structure array */
Tcl_GetIndexFromObjStruct ( interp, objv[2], ( char ** ) &options[0].optName, sizeof ( GnoclOption ), "option", TCL_EXACT, &idx );
/* does the option have a function? */
if (options[idx].func != NULL) {
Tcl_Obj *res;
options[idx].func ( interp, &options[idx], grid, &res );
Tcl_SetObjResult ( interp, res );
} else {
switch ( gnoclCget ( interp, objc, objv, G_OBJECT ( grid ), options, &idx ) ) {
case GNOCL_CGET_ERROR: { return TCL_ERROR; }
case GNOCL_CGET_HANDLED: { return TCL_OK; }
case GNOCL_CGET_NOTHANDLED: {
return cget ( interp, grid, options, idx ); }
}
}
break;
}
return TCL_OK;
}
Placing this test at the head of the sequence is more intuitive as these provide the greates complication when dealing with extraction of settings.
A GnoclOpFun woudl then be something along the lines of:
static int gnoclOptBaseLineRow ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
{
gint idx;
Tcl_GetIndexFromObj ( interp, opt->val.obj, baseLinePositions, "baseLinePosition", TCL_EXACT, &idx );
if ( ret == NULL ) { /* set value */
g_object_set ( obj, opt->propName, idx, NULL );
} else { /* get value */
g_object_get ( obj, opt->propName, &idx, NULL );
Tcl_SetObjResult ( interp, Tcl_NewStringObj ( baseLinePositions[idx], -1 ) );
}
return TCL_OK;
}
Obtaining the index of value from an array of strings or an array of structures.
static char *options[] = {
"-opt1", "-opt2", "-opt3",NULL
};
static enum optsIdx {
opt1Idx, opt2Idx, opt3Idx
};
gint idx;
/* obtain idx from an array of strings */
Tcl_GetIndexFromObj ( interp, objv[1], options, "option", TCL_EXACT, &idx );
/* obtain idx from array of structures, not an array of strings */
Tcl_GetIndexFromObjStruct ( interp, objv[1], ( char ** ) &commands[0].cmdName, sizeof ( GnoclCommand ), "command", TCL_EXACT, &idx );
-
Given this module some attention today. Added some of the more package wide options to the module and created customised handler for settin...
-
Over the past few programming sessions I've been working on producing a central point, a dashboard, around which it's possible to se...
-
Spent some time today creating some simple howto-tutorials on creating standalone Tcl/Gnocl applications using freewrap. The process is almo...