1# The functions in this file were contributed by Dave Grace
2# I have dropped them in here in no particular order
3# NOTE: I broke most of these when I changed the syntax of the
4# search and replace commands -- TMS
5
6# FormatTable
7#
8# Generates C-style data tables.
9#
10# listName is the name of a list variable containing the elements of the table
11# type is the data type (i.e. "unsigned long" or UINT32)
12# tableName is the name of the table in the C program
13# format is the printing format for each element (defaults to "\t%4d")
14# nColumns is the number of columns for the table (defaults to 4)
15proc FormatTable {args} \
16{
17	if {[llength $args] > 2} \
18	{
19		set listName [lindex $args 0]
20		set type  [lindex $args 1]
21		set tableName [lindex $args 2]
22
23		if {[llength $args] > 3} \
24		{
25			set format [lindex $args 3]
26		} \
27		else \
28		{
29			set format "\t%4d"
30		}
31
32		if {[llength $args] > 4} \
33		{
34			set nColumns [lindex $args 4]
35		} \
36		else \
37		{
38			set nColumns 4
39		}
40
41		upvar $listName list
42		set listLength [llength $list]
43		set returnString "$type\t$tableName\[$listLength\] = \{\n"
44		set i 0
45		foreach value $list \
46		{
47			if {[expr $i % $nColumns]==0} \
48			{
49				append returnString "\t"
50				set trimFormat [string trimleft $format]
51			} \
52			else \
53			{
54				set trimFormat $format
55			}
56			append returnString [format $trimFormat $value]
57
58			if {$i < [expr $listLength-1]} \
59			{
60				append returnString ","
61			}
62
63			if {([expr $i % $nColumns]==[expr $nColumns-1]) || ($i == [expr $listLength-1])} \
64			{
65				append returnString "\n"
66			}
67			incr i
68		}
69		append returnString "\};\n"
70	} \
71	else \
72	{
73		set returnString "Wrong # args: must be \"FormatTable listName type tableName ?format? ?nColumns?\""
74	}
75	return $returnString
76}
77
78
79#
80# bin2hex.tcl --
81#
82#		Implementation of bin2hex conversions for e93 editor.
83#
84# Copyright (c) 1999 D. Grace
85#
86# See the file "license.txt" for information on usage and redistribution
87# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
88#
89
90package provide hex 1.0
91namespace eval hex {
92	#internal variables
93
94	# exported functions
95	namespace export	OpenList
96}
97
98
99# hex::OpenList --
100#
101#		Convert the (binary) contents of a file to a C-style character array,
102#		suitable for including from C code.  Useful for compiling binaries directly
103#		into code to reduce load times.  Returns the buffer containing the hex data.
104#
105# Arguments:
106#		theBuffer			the buffer whose contents to convert.
107#
108# Results:
109#		A buffer name, or an error code.
110
111proc hex::OpenList { fileList } {
112	set nFiles	[llength $fileList]
113	set fileNum	0
114	set code	0
115	foreach fileName $fileList {
116		# get file size
117		if {![set code [catch {file size $fileName} error]]} {
118			# check if empty file
119			if {[set fileSize $error] > 0} {
120				# open file for reading
121				if {![set code [catch {open $fileName "r"} error]]} {
122					set fd $error
123					# set binary mode to avoid confusion on CR/LF's
124					fconfigure $fd -translation binary
125					# create the buffer for the new file
126					if {![catch {NewWindow} error]} {
127						set theBuffer $error
128					}
129					insert $theBuffer [format "unsigned char %s_data\[\] = \{\n" [file root [file tail $fileName]]]
130					set offset 0
131					while {$offset < $fileSize} {
132						insert $theBuffer [format "\t\""]
133						binary scan [read $fd 32] "H64" data
134						incr offset 32
135						set text ""
136						for {set i 0} {$i < 64} {incr i 2} {
137							append text [format "\\x%s" [string range $data [expr $i] [expr $i+1]]]
138						}
139						insert $theBuffer $text
140						insert $theBuffer [format "\"\n"]
141					}
142					insert $theBuffer [format "\};\n"]
143					close $fd
144				}
145			} else {
146				set error [format "Error: file \"%s\" contains no data" $fileName]
147				set code	1
148			}
149		}
150		if {$code} {
151			if {$fileNum == ($nFiles-1)} {
152				okdialog [format "Failed to open \"%s\":\n%s" $fileName $error]
153			} else {
154				okcanceldialog [format "Failed to open \"%s\":\n%s\n\nContinue?" $fileName $error]
155			}
156		}
157	}
158	if {!$code} {
159		return $theBuffer
160	}
161	error $error
162}
163
164
165
166# add handy menu functions
167addmenu {C}			LASTCHILD	1	"Open As Hex..."			{}		{hex::OpenList [set path [opendialog "Open File As Hex:" $curPath]];set curPath [file dirname [lindex $path 0]]}
168
169
170
171
172
173#
174# brace.tcl --
175#
176#		Implementation of brace matching for e93 editor.
177#
178# Copyright (c) 1998 D. Grace
179#
180# See the file "license.txt" for information on usage and redistribution
181# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
182#
183
184package provide brace 1.0
185namespace eval brace {
186	#internal variables
187	variable	Braces
188	variable	searchBackwards	0
189
190	# exported functions
191	namespace export	MatchBrace
192	namespace export	MatchIfDef
193
194	# build up table of braces
195	set Braces(\{.match)	\}
196	set Braces(\{.open)		1
197	set Braces(\}.match)	\{
198	set Braces(\}.open)		0
199	set Braces(\(.match)	)
200	set Braces(\(.open)		1
201	set Braces(\).match)	(
202	set Braces(\).open)		0
203	set Braces(\[.match)	\]
204	set Braces(\[.open)		1
205	set Braces(\].match)	\[
206	set Braces(\].open)		0
207}
208
209
210# brace::MatchBrace --
211#
212#		If the cursor is next to a curly brace, parenthesis, bracket etc., find
213#		the matching brace and move the cursor to it.  If no brace, beep.
214#
215# Arguments:
216#		theWindow		The e93 buffer in which to search.
217#
218# Results:
219#		The character index of the matching brace, or -1 if none found.
220
221proc brace::MatchBrace {theWindow} {
222	variable Braces
223
224	set selectionEnds [getselectionends $theWindow]
225	set start [lindex $selectionEnds 0]
226	set end [lindex $selectionEnds 1]
227	if {$start == $end} {
228		# no text is selected, so check for brace next to cursor
229		# brace to the right of cursor gets priority
230		set matchBrace ""
231		setselectionends $theWindow $start [expr $end+1]
232		set selectedText [join [selectedtextlist $theWindow]]
233		if {[regexp {\{|\}|\(|\)|\[|\]} $selectedText brace] != 0} {
234			set matchBrace $Braces($brace.match)
235			set searchForwards $Braces($brace.open)
236			if {$searchForwards} {
237				set searchStart [expr $end+1]
238			} else {
239				set searchStart $start
240			}
241		} else {
242			# check to the left of the cursor
243			setselectionends $theWindow [expr $start-1] $end
244			set selectedText [join [selectedtextlist $theWindow]]
245			if {[regexp {\{|\}|\(|\)|\[|\]} $selectedText brace] != 0} {
246				set matchBrace $Braces($brace.match)
247				set searchForwards $Braces($brace.open)
248				if {$searchForwards} {
249					set searchStart $end
250				} else {
251					set searchStart [expr $start-1]
252				}
253			}
254		}
255		if {$matchBrace != ""} {
256			# found a brace next to the cursor.  Now find the matching
257			# brace by searching in the specified direction and counting
258			# brace levels
259			setselectionends $theWindow $searchStart $searchStart
260			TextToBuffer tempFindBuffer "\\$brace|\\$matchBrace"
261			set braceLevel 1
262			while {$braceLevel > 0} {
263				if {[catch {find $theWindow tempFindBuffer [expr !$searchForwards] 0 1 0} message] == 0} {
264					if {$message != -1} {
265						# found a brace
266						set selectedText [join [selectedtextlist $theWindow]]
267						if {$selectedText == $brace} {
268							incr braceLevel 1
269						} elseif {$selectedText == $matchBrace} {
270							incr braceLevel -1
271						}
272					} else {
273						# hit the end of the file
274						break
275					}
276				}
277			}
278			if {$braceLevel == 0} {
279				# found the matching brace, and it's currently selected
280				# set cursor position to the brace
281				set selectionEnds [getselectionends $theWindow]
282				set start [lindex $selectionEnds 0]
283				setselectionends $theWindow $start $start
284				homewindow $theWindow LENIENT
285				return $start
286			}
287		}
288		setselectionends $theWindow $start $end
289	}
290	beep
291	return -1
292}
293
294
295# brace::MatchIfDef --
296#
297#		If the current selection contains a preprocessor directive like #ifdef, find the
298#		matching #else or #endif and move the cursor to it.  If the selection does not
299#		contain a token, find the closest one.  If no token found, beep.
300#
301# Arguments:
302#		theWindow		The e93 buffer in which to search.
303#
304# Results:
305#		The character index of the matching token, or -1 if none found.
306
307proc brace::MatchIfDef {theWindow} {
308	variable	searchBackwards
309
310	set code			1
311	set selectionEnds	[getselectionends $theWindow]
312	set start			[lindex $selectionEnds 0]
313	set end				[lindex $selectionEnds 1]
314	set searchExp		"^\[ \t\]*#\[ \t\]*(if|else|endif)"
315	TextToBuffer tempFindBuffer $searchExp
316	if {[regexp $searchExp [string tolower [join [selectedtextlist $theWindow]]] match token]} {
317		# the current selection contains a token - find its match if possible
318		if {$token == "if"} {
319			set searchBackwards	0
320		} elseif {$token == "endif"} {
321			set searchBackwards	1
322		} else {
323			# found an "else": search in whatever direction was searched last
324		}
325		set code	0
326		set level	1
327		while {(!$code) && ($level>0)} {
328			if {[catch {find $theWindow tempFindBuffer $searchBackwards 0 1 1} message] == 0} {
329				if {$message != -1} {
330					# found a token
331					regexp $searchExp [string tolower [join [selectedtextlist $theWindow]]] match token
332					if {$token == "else"} {
333						if {$level == 1} {
334							break
335						}
336					} else {
337						if {!$searchBackwards} {
338							if {$token == "if"} {
339								incr level 1
340							} else {
341								incr level -1
342							}
343						} else {
344							if {$token == "if"} {
345								incr level -1
346							} else {
347								incr level 1
348							}
349						}
350					}
351				} else {
352					# hit the end of the file
353					set code 1
354				}
355			}
356		}
357		if {!$code} {
358			if {$token == "if"} {
359				set searchBackwards	0
360			} elseif {$token == "endif"} {
361				set searchBackwards	1
362			} else {
363				# found an "else": search in whatever direction was searched last
364			}
365		}
366	} else {
367		# no token in the current selection, so find the nearest one (try forward first)
368		if {(![catch {find $theWindow tempFindBuffer 0 0 1 1} message]) && ($message!=-1)} {
369			set code 0
370		} elseif {(![catch {find $theWindow tempFindBuffer 1 0 1 1} message]) && ($message!=-1)} {
371			set code 0
372		}
373		if {!$code} {
374			regexp $searchExp [string tolower [join [selectedtextlist $theWindow]]] match token
375			if {$token == "if"} {
376				set searchBackwards	0
377			} elseif {$token == "endif"} {
378				set searchBackwards	1
379			} else {
380				# found an "else": search in whatever direction was searched last
381			}
382		}
383	}
384	if {!$code} {
385		# set cursor position to the token
386		homewindow $theWindow LENIENT
387		return $start
388	}
389	setselectionends $theWindow $start $end
390	beep
391	return -1
392}
393
394
395# Bind keys to various useful things.
396# l=caps lock, s=shift, c=control, 0-7 are additional modifiers such as command, alt, option, command, etc...
397# Bind flags		 lsc01234567 (x means don't care, 0 means not pressed, 1 means pressed)
398
399bindkey bracketleft			{x0100000000} {brace::MatchBrace [ActiveWindowOrBeep]}
400bindkey bracketright		{x0100000000} {brace::MatchBrace [ActiveWindowOrBeep]}
401bindkey bracketleft			{x1100000000} {brace::MatchIfDef [ActiveWindowOrBeep]}
402bindkey bracketright		{x1100000000} {brace::MatchIfDef [ActiveWindowOrBeep]}
403
404
405
406##############################################################################
407##############################################################################
408##############################################################################
409
410# new updated bracketing stuff
411
412##############################################################################
413##############################################################################
414##############################################################################
415
416
417#
418# brace.tcl --
419#
420#		Implementation of brace matching for e93 editor.
421#
422# Copyright (c) 1998 D. Grace
423#
424# See the file "license.txt" for information on usage and redistribution
425# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
426#
427
428package provide brace 1.0
429namespace eval brace {
430	#internal variables
431	variable	Braces
432	variable	searchBackwards	0
433
434	# exported functions
435	namespace export	MatchBrace
436	namespace export	MatchIfDef
437
438	# build up table of braces
439	set Braces(\{.match)	\}
440	set Braces(\{.open)		1
441	set Braces(\}.match)	\{
442	set Braces(\}.open)		0
443	set Braces(\(.match)	)
444	set Braces(\(.open)		1
445	set Braces(\).match)	(
446	set Braces(\).open)		0
447	set Braces(\[.match)	\]
448	set Braces(\[.open)		1
449	set Braces(\].match)	\[
450	set Braces(\].open)		0
451}
452
453
454# brace::MatchBrace --
455#
456#		If the cursor is next to a curly brace, parenthesis, bracket etc., find
457#		the matching brace and move the cursor to it.  If no brace, beep.
458#
459# Arguments:
460#		theWindow		The e93 buffer in which to search.
461#
462# Results:
463#		The character index of the matching brace, or -1 if none found.
464
465proc brace::MatchBrace {theWindow} {
466	variable Braces
467
468	set selectionEnds [getselectionends $theWindow]
469	set start [lindex $selectionEnds 0]
470	set end [lindex $selectionEnds 1]
471	if {$start == $end} {
472		# no text is selected, so check for brace next to cursor
473		# brace to the right of cursor gets priority
474		set matchBrace ""
475		setselectionends $theWindow $start [expr $end+1]
476		set selectedText [join [selectedtextlist $theWindow]]
477		if {[regexp {\{|\}|\(|\)|\[|\]} $selectedText brace] != 0} {
478			set matchBrace $Braces($brace.match)
479			set searchForwards $Braces($brace.open)
480			if {$searchForwards} {
481				set searchStart [expr $end+1]
482			} else {
483				set searchStart $start
484			}
485		} else {
486			# check to the left of the cursor
487			setselectionends $theWindow [expr $start-1] $end
488			set selectedText [join [selectedtextlist $theWindow]]
489			if {[regexp {\{|\}|\(|\)|\[|\]} $selectedText brace] != 0} {
490				set matchBrace $Braces($brace.match)
491				set searchForwards $Braces($brace.open)
492				if {$searchForwards} {
493					set searchStart $end
494				} else {
495					set searchStart [expr $start-1]
496				}
497			}
498		}
499		if {$matchBrace != ""} {
500			# found a brace next to the cursor.  Now find the matching
501			# brace by searching in the specified direction and counting
502			# brace levels
503			setselectionends $theWindow $searchStart $searchStart
504			TextToBuffer tempFindBuffer "\\$brace|\\$matchBrace"
505			set braceLevel 1
506			while {$braceLevel > 0} {
507				set findArgs "-regex"
508				if {!$searchForwards} {
509					append findArgs " -backward"
510				}
511				if {[catch {eval find \$theWindow tempFindBuffer $findArgs} message] == 0} {
512					if {$message != -1} {
513						# found a brace
514						set selectedText [join [selectedtextlist $theWindow]]
515						if {$selectedText == $brace} {
516							incr braceLevel 1
517						} elseif {$selectedText == $matchBrace} {
518							incr braceLevel -1
519						}
520					} else {
521						# hit the end of the file
522						break
523					}
524				}
525			}
526			if {$braceLevel == 0} {
527				# found the matching brace, and it's currently selected
528				# set cursor position to the brace
529				set selectionEnds [getselectionends $theWindow]
530				set start [lindex $selectionEnds 0]
531				setselectionends $theWindow $start $start
532				eval homewindow \$theWindow [getselectionends $theWindow] -lenient
533				return $start
534			}
535		}
536		setselectionends $theWindow $start $end
537	}
538	beep
539	return -1
540}
541
542
543# brace::MatchIfDef --
544#
545#		If the current selection contains a preprocessor directive like #ifdef, find the
546#		matching #else or #endif and move the cursor to it.  If the selection does not
547#		contain a token, find the closest one.  If no token found, beep.
548#
549# Arguments:
550#		theWindow		The e93 buffer in which to search.
551#
552# Results:
553#		The character index of the matching token, or -1 if none found.
554
555proc brace::MatchIfDef {theWindow} {
556	variable	searchBackwards
557
558	set code			1
559	set selectionEnds	[getselectionends $theWindow]
560	set start			[lindex $selectionEnds 0]
561	set end				[lindex $selectionEnds 1]
562	set searchExp		"^\[ \t\]*#\[ \t\]*(if|else|endif)"
563	TextToBuffer tempFindBuffer $searchExp
564	if {[regexp $searchExp [string tolower [join [selectedtextlist $theWindow]]] match token]} {
565		# the current selection contains a token - find its match if possible
566		if {$token == "if"} {
567			set searchBackwards	0
568		} elseif {$token == "endif"} {
569			set searchBackwards	1
570		} else {
571			# found an "else": search in whatever direction was searched last
572		}
573		set code	0
574		set level	1
575		while {(!$code) && ($level>0)} {
576			set findArgs "-regex -ignorecase"
577			if {$searchBackwards} {
578				append findArgs " -backward"
579			}
580			if {[catch {find $theWindow tempFindBuffer $findArgs} message] == 0} {
581				if {$message != -1} {
582					# found a token
583					regexp $searchExp [string tolower [join [selectedtextlist $theWindow]]] match token
584					if {$token == "else"} {
585						if {$level == 1} {
586							break
587						}
588					} else {
589						if {!$searchBackwards} {
590							if {$token == "if"} {
591								incr level 1
592							} else {
593								incr level -1
594							}
595						} else {
596							if {$token == "if"} {
597								incr level -1
598							} else {
599								incr level 1
600							}
601						}
602					}
603				} else {
604					# hit the end of the file
605					set code 1
606				}
607			}
608		}
609		if {!$code} {
610			if {$token == "if"} {
611				set searchBackwards	0
612			} elseif {$token == "endif"} {
613				set searchBackwards	1
614			} else {
615				# found an "else": search in whatever direction was searched last
616			}
617		}
618	} else {
619		# no token in the current selection, so find the nearest one (try forward first)
620		if {(![catch {find $theWindow tempFindBuffer -regex -ignorecase} message]) && ($message!=-1)} {
621			set code 0
622		} elseif {(![catch {find $theWindow tempFindBuffer -backward -regex -ignorecase} message]) && ($message!=-1)} {
623			set code 0
624		}
625		if {!$code} {
626			regexp $searchExp [string tolower [join [selectedtextlist $theWindow]]] match token
627			if {$token == "if"} {
628				set searchBackwards	0
629			} elseif {$token == "endif"} {
630				set searchBackwards	1
631			} else {
632				# found an "else": search in whatever direction was searched last
633			}
634		}
635	}
636	if {!$code} {
637		# set cursor position to the token
638		eval homewindow \$theWindow [getselectionends $theWindow] -lenient
639		return $start
640	}
641	setselectionends $theWindow $start $end
642	beep
643	return -1
644}
645