Переглянути джерело

Import most components (GCC/GAS patches, IDE, tigcc.exe, hsf2RC, ld-tigcc, tprbuilder).

git-svn-id: file:///var/svn/tigccpp/trunk@9 9552661e-59e3-4036-b4f2-dbe53926924f
kevinkofler 19 роки тому
батько
коміт
8e690f510e
100 змінених файлів з 35406 додано та 0 видалено
  1. 277 0
      tigcc/components/HTMLHelpUnit.pas
  2. 3671 0
      tigcc/components/MemoComponentUnit.pas
  3. 65 0
      tigcc/components/Source Editor Readme.txt
  4. 2166 0
      tigcc/components/SourceEditUnit.pas
  5. 69 0
      tigcc/components/URLLabelUnit.pas
  6. 180 0
      tigcc/gcc/ChangeLog-gas.txt
  7. 818 0
      tigcc/gcc/ChangeLog.txt
  8. 1 0
      tigcc/gcc/Makefile-empty
  9. 131 0
      tigcc/gcc/cleansources.sh
  10. 1006 0
      tigcc/gcc/gas-2.14-tigcc-11.diff
  11. 7225 0
      tigcc/gcc/gcc-3.3.3-tigcc-8.diff
  12. 61 0
      tigcc/general/FileReadToBufferThreadUnit.pas
  13. 40 0
      tigcc/general/HandleWaitThreadUnit.pas
  14. 698 0
      tigcc/general/ObjList.pas
  15. 895 0
      tigcc/general/UtilsDos.pas
  16. 30 0
      tigcc/general/UtilsSys.pas
  17. 114 0
      tigcc/general/UtilsWin.pas
  18. 340 0
      tigcc/hsf2rc/License.txt
  19. 8 0
      tigcc/hsf2rc/NotDefinedRom_calls
  20. 19 0
      tigcc/hsf2rc/db92_alias
  21. 206 0
      tigcc/hsf2rc/doorsos.h.end
  22. 43 0
      tigcc/hsf2rc/hsf2RC.txt
  23. 171 0
      tigcc/hsf2rc/hsf2rc.cpp
  24. 92 0
      tigcc/hsf2rc/os.h.end
  25. BIN
      tigcc/ide/AboutUnit.dfm
  26. 55 0
      tigcc/ide/AboutUnit.pas
  27. 15 0
      tigcc/ide/CalcUnit.pas
  28. 494 0
      tigcc/ide/CodeCompletion/CodeCompletion.pas
  29. BIN
      tigcc/ide/CodeCompletion/CompletionForm.dfm
  30. 776 0
      tigcc/ide/CodeCompletion/CompletionForm.pas
  31. BIN
      tigcc/ide/CodeCompletion/Editor/uBatch.dfm
  32. 129 0
      tigcc/ide/CodeCompletion/Editor/uBatch.pas
  33. BIN
      tigcc/ide/CodeCompletion/Editor/uEditor.dfm
  34. 490 0
      tigcc/ide/CodeCompletion/Editor/uEditor.pas
  35. 189 0
      tigcc/ide/CodeCompletion/Editor/uHSFParser.pas
  36. 196 0
      tigcc/ide/CodeCompletion/HtFormatting.pas
  37. BIN
      tigcc/ide/CodeCompletion/PrefFrame.dfm
  38. 108 0
      tigcc/ide/CodeCompletion/PrefFrame.pas
  39. BIN
      tigcc/ide/CodeCompletion/TmpltForm.dfm
  40. 200 0
      tigcc/ide/CodeCompletion/TmpltForm.pas
  41. BIN
      tigcc/ide/ColorsUnit.dfm
  42. 120 0
      tigcc/ide/ColorsUnit.pas
  43. BIN
      tigcc/ide/CustomStyleUnit.dfm
  44. 114 0
      tigcc/ide/CustomStyleUnit.pas
  45. 72 0
      tigcc/ide/FolderUnit.pas
  46. BIN
      tigcc/ide/FunctionsWinUnit.dfm
  47. 48 0
      tigcc/ide/FunctionsWinUnit.pas
  48. 36 0
      tigcc/ide/IDE.cfg
  49. 104 0
      tigcc/ide/IDE.dof
  50. 65 0
      tigcc/ide/IDE.dpr
  51. 127 0
      tigcc/ide/IDE.dsk
  52. BIN
      tigcc/ide/IDE.res
  53. 77 0
      tigcc/ide/LinkDLLUnit.pas
  54. 682 0
      tigcc/ide/LinkUnit.pas
  55. BIN
      tigcc/ide/MainUnit.dfm
  56. 5363 0
      tigcc/ide/MainUnit.pas
  57. 735 0
      tigcc/ide/MasterUnit.pas
  58. BIN
      tigcc/ide/NewFolderUnit.dfm
  59. 33 0
      tigcc/ide/NewFolderUnit.pas
  60. BIN
      tigcc/ide/NewsUnit.dfm
  61. 250 0
      tigcc/ide/NewsUnit.pas
  62. BIN
      tigcc/ide/OpenFileStatusUnit.dfm
  63. 33 0
      tigcc/ide/OpenFileStatusUnit.pas
  64. 598 0
      tigcc/ide/ParsingUnit.pas
  65. BIN
      tigcc/ide/PreferencesUnit.dfm
  66. 491 0
      tigcc/ide/PreferencesUnit.pas
  67. 281 0
      tigcc/ide/ProcessUnit.pas
  68. BIN
      tigcc/ide/ProgramOptionsUnit.dfm
  69. 202 0
      tigcc/ide/ProgramOptionsUnit.pas
  70. BIN
      tigcc/ide/ProgramOutputUnit.dfm
  71. 33 0
      tigcc/ide/ProgramOutputUnit.pas
  72. BIN
      tigcc/ide/ProjectOptionsUnit.dfm
  73. 262 0
      tigcc/ide/ProjectOptionsUnit.pas
  74. BIN
      tigcc/ide/SendProgressUnit.dfm
  75. 51 0
      tigcc/ide/SendProgressUnit.pas
  76. 2655 0
      tigcc/ide/SourceFileUnit.pas
  77. BIN
      tigcc/ide/SourceFileWinUnit.dfm
  78. 789 0
      tigcc/ide/SourceFileWinUnit.pas
  79. BIN
      tigcc/ide/StartupScreenUnit.dfm
  80. 58 0
      tigcc/ide/StartupScreenUnit.pas
  81. BIN
      tigcc/ide/StartupUnit.dfm
  82. BIN
      tigcc/ide/StyleSelectionUnit.dfm
  83. 75 0
      tigcc/ide/StyleSelectionUnit.pas
  84. BIN
      tigcc/ide/SyntaxProgressUnit.dfm
  85. BIN
      tigcc/ide/ToolPropertiesUnit.dfm
  86. 82 0
      tigcc/ide/ToolPropertiesUnit.pas
  87. 40 0
      tigcc/ide/ToolsListUnit.pas
  88. BIN
      tigcc/ide/ToolsUnit.dfm
  89. 179 0
      tigcc/ide/ToolsUnit.pas
  90. BIN
      tigcc/ide/VTIStartUnit.dfm
  91. 76 0
      tigcc/ide/VTIStartUnit.pas
  92. 12 0
      tigcc/ide/VersionUnit.pas
  93. BIN
      tigcc/ide/WordListUnit.dfm
  94. 93 0
      tigcc/ide/WordListUnit.pas
  95. 340 0
      tigcc/ld-tigcc/GPL.txt
  96. 71 0
      tigcc/ld-tigcc/Makefile
  97. 5 0
      tigcc/ld-tigcc/ToDo.txt
  98. 82 0
      tigcc/ld-tigcc/ar/data.h
  99. 61 0
      tigcc/ld-tigcc/ar/dump.c
  100. 33 0
      tigcc/ld-tigcc/ar/dump.h

+ 277 - 0
tigcc/components/HTMLHelpUnit.pas

@@ -0,0 +1,277 @@
+unit HTMLHelpUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	ShellAPI, Menus;
+
+const
+	HH_DISPLAY_TOPIC        = $0000;
+	HH_HELP_FINDER          = $0000;  // WinHelp equivalent
+	HH_DISPLAY_TOC          = $0001;
+	HH_DISPLAY_INDEX        = $0002;
+	HH_DISPLAY_SEARCH       = $0003;
+	HH_SET_WIN_TYPE         = $0004;
+	HH_GET_WIN_TYPE         = $0005;
+	HH_GET_WIN_HANDLE       = $0006;
+	HH_ENUM_INFO_TYPE       = $0007;  // Get Info type name, call repeatedly to enumerate, -1 at end
+	HH_SET_INFO_TYPE        = $0008;  // Add Info type to filter.
+	HH_SYNC                 = $0009;
+	HH_RESERVED1            = $000A;
+	HH_RESERVED2            = $000B;
+	HH_RESERVED3            = $000C;
+	HH_KEYWORD_LOOKUP       = $000D;
+	HH_DISPLAY_TEXT_POPUP   = $000E;  // display string resource id or text in a popup window
+	HH_HELP_CONTEXT         = $000F;  // display mapped numeric value in dwData
+	HH_TP_HELP_CONTEXTMENU  = $0010;  // text popup help, same as WinHelp HELP_CONTEXTMENU
+	HH_TP_HELP_WM_HELP      = $0011;  // text popup help, same as WinHelp HELP_WM_HELP
+	HH_CLOSE_ALL            = $0012;  // close all windows opened directly or indirectly by the caller
+	HH_ALINK_LOOKUP         = $0013;  // ALink version of HH_KEYWORD_LOOKUP
+	HH_GET_LAST_ERROR       = $0014;  // not currently implemented // See HHERROR.h
+	HH_ENUM_CATEGORY        = $0015;  // Get category name, call repeatedly to enumerate, -1 at end
+	HH_ENUM_CATEGORY_IT     = $0016;  // Get category info type members, call repeatedly to enumerate, -1 at end
+	HH_RESET_IT_FILTER      = $0017;  // Clear the info type filter of all info types.
+	HH_SET_INCLUSIVE_FILTER = $0018;  // set inclusive filtering method for untyped topics to be included in display
+	HH_SET_EXCLUSIVE_FILTER = $0019;  // set exclusive filtering method for untyped topics to be excluded from display
+	HH_INITIALIZE           = $001C;  // Initializes the help system.
+	HH_UNINITIALIZE         = $001D;  // Uninitializes the help system.
+	HH_PRETRANSLATEMESSAGE  = $00FD;  // Pumps messages. (NULL, NULL, MSG*).
+	HH_SET_GLOBAL_PROPERTY  = $00FC;  // Set a global property. (NULL, NULL, HH_GPROP)
+
+type
+	DWordPtr = DWord;
+
+	THHAKLink = packed record
+		cbStruct: Integer;     // Size of this structure
+		fReserved: Bool;       // Must be FALSE (really!)
+		pszKeywords: LPCTStr;  // Semi-colon separated keywords
+		pszUrl: LPCTStr;       // URL to jump to if no keywords found (may be NULL)
+		pszMsgText: LPCTStr;   // Message text to display in MessageBox if pszUrl is NULL and no keyword match
+		pszMsgTitle: LPCTStr;  // Message title to display in MessageBox if pszUrl is NULL and no keyword match
+		pszWindow: LPCTStr;    // Window to display URL in
+		fIndexOnFail: Bool;    // Displays index if keyword lookup fails.
+	end;
+	HH_AKLINK = THHAKLink;
+	tagHH_AKLINK = HH_AKLINK;
+	PHHAKLink = ^THHAKLink;
+
+	THHFTSQuery = record
+		cbStruct: Integer;        // Size of structure in bytes.
+		fUniCodeStrings: Bool;    // TRUE if all strings are unicode.
+		pszSearchQuery: LPCTStr;  // String containing the search query.
+		iProximity: LongInt;      // Word proximity.
+		fStemmedSearch: Bool;     // TRUE for StemmedSearch only.
+		TitleOnly: Bool;          // TRUE for Title search only.
+		fExecute: Bool;           // TRUE to initiate the search.
+		pszWindow: LPCTStr;       // Window to display in
+	end;
+	HH_FTS_QUERY = THHFTSQuery;
+	tagHH_FTS_QUERY = HH_FTS_QUERY;
+
+	THtmlHelpAProc = function(hwndCaller: HWnd; pszFile: PAnsiChar; uCommand: UInt; dwData: DWordPtr): HWnd; stdcall;
+	THtmlHelpWProc = function(hwndCaller: HWnd; pszFile: PWideChar; uCommand: UInt; dwData: DWordPtr): HWnd; stdcall;
+	THtmlHelpProc = function(hwndCaller: HWnd; pszFile: PChar; uCommand: UInt; dwData: DWordPtr): HWnd; stdcall;
+
+var
+	HtmlHelpA: THtmlHelpAProc;
+	HtmlHelpW: THtmlHelpWProc;
+	HtmlHelp: THtmlHelpProc;
+
+resourcestring
+	SHTMLHelpNotInstalled = 'The HTML Help Viewer is not installed. Download it at www.microsoft.com.';
+	SHTMLHelpFileNotFound = 'The help file could not be found.';
+
+type
+	EHTMLHelp = class(Exception);
+	EHTMLHelpNotInstalled = class(EHTMLHelp);
+	EHTMLHelpFileNotFound = class(EHTMLHelp);
+
+	THTMLHelp = class(TComponent)
+	private
+		FWindowHandle: HWnd;
+		FCookie: DWord;
+		FWindowType: string;
+		FFileName: string;
+		FCurrentTopic: string;
+		FMaximizeOnShow: Boolean;
+		procedure WndProc(var Msg: TMessage);
+		function GetFileString: string;
+	protected
+		property CurrentTopic: string read FCurrentTopic write FCurrentTopic;
+		property FileString: string read GetFileString;
+	public
+		constructor Create(AOwner: TComponent); override;
+		destructor Destroy; override;
+		function SendMessage(pszFile: PChar; uCommand: UInt; dwData: DWordPtr): HWnd;
+		function Display: Boolean;
+		function DisplayTopic(const Topic: string): Boolean;
+		function KeywordLookup(const Keyword: string): Boolean;
+		function KeywordLookupEx(const Link: THHAKLink): Boolean;
+		function DisplayContentsTab: Boolean;
+		function DisplayIndexTab: Boolean;
+		function DisplaySearchTab: Boolean;
+		procedure CloseAllWindows;
+	published
+		property FileName: string read FFileName write FFileName;
+		property WindowType: string read FWindowType write FWindowType;
+		property MaximizeOnShow: Boolean read FMaximizeOnShow write FMaximizeOnShow;
+	end;
+
+procedure Register;
+
+const
+	hhctrl = 'hhctrl.ocx';
+
+implementation
+
+procedure Register;
+begin
+	RegisterComponents('Help', [THTMLHelp]);
+end;
+
+{ THTMLHelp }
+
+procedure THTMLHelp.CloseAllWindows;
+begin
+	SendMessage (nil, HH_CLOSE_ALL, 0);
+end;
+
+constructor THTMLHelp.Create;
+begin
+	inherited;
+	if Assigned (HtmlHelp) then begin
+		FWindowHandle := AllocateHWnd (WndProc);
+		HtmlHelp (0, nil, HH_INITIALIZE, DWordPtr (@FCookie));
+	end;
+end;
+
+destructor THTMLHelp.Destroy;
+begin
+	if Assigned (HtmlHelp) then begin
+		CloseAllWindows;
+		HtmlHelp (0, nil, HH_UNINITIALIZE, DWordPtr (FCookie));
+		DeallocateHWnd (FWindowHandle);
+	end;
+	inherited;
+end;
+
+function THTMLHelp.Display: Boolean;
+begin
+	Result := DisplayTopic ('');
+end;
+
+function THTMLHelp.DisplayContentsTab: Boolean;
+begin
+	Display;
+	Result := SendMessage (PChar (FileString), HH_DISPLAY_TOC, 0) <> 0;
+end;
+
+function THTMLHelp.DisplayIndexTab: Boolean;
+begin
+	Display;
+	Result := SendMessage (PChar (FileString), HH_DISPLAY_INDEX, 0) <> 0;
+end;
+
+function THTMLHelp.DisplaySearchTab: Boolean;
+var
+	Query: THHFTSQuery;
+begin
+	Display;
+	with Query do begin
+		cbStruct := SizeOf (Query);
+		fUniCodeStrings := False;
+		pszSearchQuery := '';
+		iProximity := 0;
+		fStemmedSearch := False;
+		TitleOnly := False;
+		fExecute := False;
+		pszWindow := PChar (WindowType);
+	end;
+	Result := SendMessage (PChar (FileString), HH_DISPLAY_SEARCH, DWordPtr (@Query)) <> 0;
+end;
+
+function THTMLHelp.DisplayTopic(const Topic: string): Boolean;
+begin
+	CurrentTopic := Topic;
+	Result := SendMessage (PChar (FileString), HH_DISPLAY_TOPIC, 0) <> 0;
+end;
+
+function THTMLHelp.GetFileString: string;
+begin
+	if FileName = '' then
+		Result := ''
+	else begin
+		Result := FileName;
+		if CurrentTopic <> '' then
+			Result := Result + '::/' + CurrentTopic;
+		if WindowType <> '' then
+			Result := Result + '>' + WindowType;
+	end;
+end;
+
+function THTMLHelp.KeywordLookup(const Keyword: string): Boolean;
+var
+	Link: THHAKLink;
+begin
+	if Length (Keyword) > 0 then begin
+		FillChar (Link, SizeOf (Link), 0);
+		with Link do begin
+			cbStruct := SizeOf (Link);
+			pszKeywords := PChar (Keyword);
+			fIndexOnFail := True;
+		end;
+		Result := KeywordLookupEx (Link);
+	end else
+		Result := False;
+end;
+
+function THTMLHelp.KeywordLookupEx(const Link: THHAKLink): Boolean;
+begin
+	Result := SendMessage (PChar (FileName), HH_KEYWORD_LOOKUP, DWord (@Link)) <> 0;
+end;
+
+function THTMLHelp.SendMessage(pszFile: PChar; uCommand: UInt;
+	dwData: DWordPtr): HWnd;
+begin
+	if Assigned (pszFile) and (pszFile <> '') and (not FileExists (FileName)) then
+		raise EHTMLHelpFileNotFound.Create (SHTMLHelpFileNotFound);
+	if Assigned (HtmlHelp) then
+		Result := HtmlHelp (FWindowHandle, pszFile, uCommand, dwData)
+	else
+		raise EHTMLHelpNotInstalled.Create (SHTMLHelpNotInstalled);
+	if (Result <> 0) and MaximizeOnShow then
+		ShowWindow (Result, SW_MAXIMIZE);
+end;
+
+procedure THTMLHelp.WndProc(var Msg: TMessage);
+begin
+	if Assigned (HtmlHelp) then
+		try
+			if HtmlHelp (0, nil, HH_PRETRANSLATEMESSAGE, DWordPtr (@Msg)) = 0 then
+				with Msg do
+					Result := DefWindowProc (FWindowHandle, Msg, wParam, lParam);
+		except
+			Application.HandleException (Self);
+		end
+	else
+		with Msg do
+			Result := DefWindowProc (FWindowHandle, Msg, wParam, lParam);
+end;
+
+{ HTML Help Initialization }
+
+var
+	LibHandle: THandle;
+
+initialization
+	LibHandle := LoadLibrary (hhctrl);
+	if LibHandle <> 0 then begin
+		@HtmlHelpA := GetProcAddress (LibHandle, 'HtmlHelpA');
+		@HtmlHelpW := GetProcAddress (LibHandle, 'HtmlHelpW');
+		@HtmlHelp := GetProcAddress (LibHandle, 'HtmlHelpA');
+	end;
+finalization
+	if LibHandle <> 0 then
+		FreeLibrary (LibHandle);
+end.

+ 3671 - 0
tigcc/components/MemoComponentUnit.pas

@@ -0,0 +1,3671 @@
+
+{*******************************************************}
+{                                                       }
+{       TMemo-Compatible Component v1.19                }
+{                                                       }
+{       Copyright (c) 2000-2004 Sebastian Reichelt      }
+{                                                       }
+{*******************************************************}
+
+unit MemoComponentUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Forms, Graphics, Controls, StdCtrls, ObjList;
+
+type
+	TMCRanges = class;
+	TCustomRange = class;
+	TMCRange = class;
+	TWholeTextRange = class;
+	TVisibleRange = class;
+	TSelectionRange = class;
+	TCustomFormattedRange = class;
+	TFormattedRange = class;
+	TNormalFormattedRange = class;
+
+	TFormattedRangeArray = array of TCustomFormattedRange;
+
+	TIntegerList = class;
+
+	TTextCell = record
+		Row,
+		Col: Integer;
+	end;
+
+	PUndoOperation = ^TUndoOperation;
+	TUndoOperation = record
+		RStart,
+		REnd: Integer;
+		NewText: string;
+		NextItem: PUndoOperation;
+	end;
+
+	TReplaceEvent = procedure(Sender: TObject; Pos, Change: Integer) of object;
+
+	TCurCursor = (ccNone, ccIBeam, ccArrow, ccDrag);
+
+	{	Note:
+		The key element of the TMemoComponent class is the ReplaceText
+		method.  Its intent is to replace a piece of text (range) with as
+		little destruction as possible.  All values, for example the line
+		index table and tracked ranges, are kept intact.  Do not attempt to
+		call this procedure directly or to modify the memo's text directly
+		using FText.  Instead, create a range and use its Text property.
+		The range can be tracked or not, but be sure to set the Editor
+		property if it is not tracked.
+		To change the behavior when drawing text, override the virtual
+		CreateSplitRanges method.  The result must be an array of
+		TCustomFormattedRange. }
+
+	TMemoComponent = class(TCustomControl)
+	private
+		FHasFocus: Boolean;
+		FCaretCreated: Boolean;
+		FSelecting: Boolean;
+		FDragging: Boolean;
+		FStartDrag: Boolean;
+		FDblClicked: Boolean;
+		FLineStarts: TIntegerList;
+		FScrollBars: TScrollStyle;
+		FBorderStyle: TBorderStyle;
+		FReadOnly: Boolean;
+		FOnChange: TNotifyEvent;
+		FText: TCaption;
+		FTrackedRanges: TMCRanges;
+		FWholeText: TCustomRange;
+		FLines: TStrings;
+		FVisibleRange: TVisibleRange;
+		FSelection: TSelectionRange;
+		FLongestLineLength: Integer;
+		FAlwaysShowCaret: Boolean;
+		FLeftMargin: Integer;
+		FTopMargin: Integer;
+		FTabSize: Integer;
+		FOnSelectionChange: TNotifyEvent;
+		FTextLength: Integer;
+		FBitmapped: Boolean;
+		FOnChangePrivate: TNotifyEvent;
+		FAllowUndo: Boolean;
+		FOnReplaceText: TReplaceEvent;
+		FForbiddenFontStyles: TFontStyles;
+		FDrawingSuspended: Boolean;
+		FDragDropEditing: Boolean;
+		FRemoveTrailingSpaces: Boolean;
+    FAutoIndent: Boolean;
+		procedure CMFontChanged(var Message: TMessage); message cm_FontChanged;
+		procedure WMSize(var Message: TWMSize); message wm_Size;
+		procedure WMHScroll(var Message: TWMHScroll); message wm_HScroll;
+		procedure WMVScroll(var Message: TWMVScroll); message wm_VScroll;
+		procedure WMSetFocus(var Message: TWMSetFocus); message wm_SetFocus;
+		procedure WMKillFocus(var Message: TWMKillFocus); message wm_KillFocus;
+		procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message wm_EraseBkgnd;
+		procedure CMWantSpecialKey(var Message: TCMWantSpecialKey); message cm_WantSpecialKey;
+		procedure WMKeyDown(var Message: TWMKeyDown); message wm_KeyDown;
+		procedure WMKeyUp(var Message: TWMKeyUp); message wm_KeyUp;
+		procedure WMClear(var Message: TWMClear); message wm_Clear;
+		procedure WMCut(var Message: TWMCut); message wm_Cut;
+		procedure WMCopy(var Message: TWMCopy); message wm_Copy;
+		procedure WMPaste(var Message: TWMPaste); message wm_Paste;
+		procedure WMSetText(var Message: TWMSetText); message wm_SetText;
+		procedure WMGetText(var Message: TWMGetText); message wm_GetText;
+		procedure WMGetTextLength(var Message: TWMGetTextLength); message wm_GetTextLength;
+		procedure WMTimer(var Message: TWMTimer); message wm_Timer;
+		procedure EMUndo(var Message: TMessage); message em_Undo;
+		procedure EMCanUndo(var Message: TMessage); message em_CanUndo;
+		procedure CMMouseWheel(var Message: TCMMouseWheel); message cm_MouseWheel;
+		procedure WMGetDlgCode(var Message: TWMGetDlgCode); message wm_GetDlgCode;
+		procedure SetText(const Value: TCaption);
+		procedure SetScrollBars(const Value: TScrollStyle);
+		procedure SetBorderStyle(const Value: TBorderStyle);
+		procedure SetReadOnly(const Value: Boolean);
+		procedure SetLines(const Value: TStrings);
+		function GetLineCount: Integer;
+		function GetLineLength(LineIndex: Integer): Integer;
+		function GetVisualLineLength(LineIndex: Integer): Integer;
+		function GetSelLength: Integer;
+		function GetSelStart: Integer;
+		procedure SetSelLength(const Value: Integer);
+		procedure SetSelStart(const Value: Integer);
+		procedure SetAlwaysShowCaret(const Value: Boolean);
+		procedure SetLeftMargin(const Value: Integer);
+		procedure SetTopMargin(const Value: Integer);
+		procedure SetTabSize(const Value: Integer);
+		function GetCanRedo: Boolean;
+		function GetCanUndo: Boolean;
+		procedure SetBitmapped(const Value: Boolean);
+		procedure SetAllowUndo(const Value: Boolean);
+		procedure SetRemoveTrailingSpaces(const Value: Boolean);
+		procedure SetHasFocus(const Value: Boolean);
+	protected
+		FontHeight,
+		FontWidth,
+		PageHeight,
+		PageWidth: Integer;
+		DrawBmp: TBitmap;
+		FUndoStack,
+		FRedoStack: PUndoOperation;
+		FInUndo,
+		DontNotify: Boolean;
+		DragOrigRange: TMCRange;
+		FCurCursor: TCurCursor;
+		FTempCursor: Boolean;
+		FCursorIBeam: HCursor;
+		FCursorArrow: HCursor;
+		FCursorDrag: HCursor;
+		procedure CreateParams(var Params: TCreateParams); override;
+		procedure CreateWnd; override;
+		procedure ReplaceText(Range: TCustomRange; const NewText: string); virtual;
+		procedure DrawTextLine(Range: TCustomRange; Left, Top: Integer; NextTabStop: Integer); virtual;
+		function CreateSplitRanges(Range: TCustomRange): TFormattedRangeArray; virtual;
+		procedure DrawBorder(LeftRect, TopRect: TRect; Canvas: TCanvas); virtual;
+		procedure TextChangeNotification(StartPos, OldLength, NewLength: Integer); dynamic;
+		procedure TextChangeNotificationAfter; dynamic;
+		procedure Change; dynamic;
+		procedure SelectionChange; dynamic;
+		procedure UpdateFontSize; virtual;
+		procedure UpdatePageSize; virtual;
+		procedure UpdateDrawBmp; virtual;
+		procedure ReCreateCaret; virtual;
+		procedure FreeCaret; virtual;
+		procedure Paint; override;
+		procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
+		procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
+		procedure MouseMoveInternal(X, Y: Integer); virtual;
+		procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
+		procedure KeyPress(var Key: Char); override;
+		procedure DblClick; override;
+		function GetLastUndo: TUndoOperation; virtual;
+		function GetLastRedo: TUndoOperation; virtual;
+		function CreateUndoBeginEndBlock: PUndoOperation; virtual;
+		function IsUndoBeginEndBlock(Op: PUndoOperation): Boolean; virtual;
+		procedure MakeUndoOperation(Op: PUndoOperation); virtual;
+		procedure MakeRedoOperation(Op: PUndoOperation); virtual;
+		procedure CancelDragging;
+		procedure SetCurCursor(NewCursor: TCurCursor = ccNone; Temporary: Boolean = False);
+		property HasFocus: Boolean read FHasFocus write SetHasFocus;
+	public
+		constructor Create(AOwner: TComponent); override;
+		destructor Destroy; override;
+		procedure Clear; virtual;
+		procedure HandleKeyPress(var Key: Char);
+		procedure HandleKeyDown(var Key: Word; Shift: TShiftState);
+		procedure HandleKeyUp(var Key: Word; Shift: TShiftState);
+		function CharIdxToCell(CharIdx: Integer): TTextCell; virtual;
+		function CellToCharIdx(Cell: TTextCell): Integer; virtual;
+		function ScrPointToScrCell(P: TPoint): TTextCell; virtual;
+		function ScrCellToScrPoint(Cell: TTextCell): TPoint; virtual;
+		function TabSpacesAtPos(P: Integer): Integer; virtual;
+		function CellToScrCol(Cell: TTextCell): Integer; virtual;
+		procedure CellFromScrCol(var Cell: TTextCell); virtual;
+		function CellFromScrColToScrCol(var Cell: TTextCell): Integer; virtual;
+		procedure SelectAll;
+		procedure ClearSelection;
+		procedure CutToClipboard;
+		procedure CopyToClipboard;
+		procedure PasteFromClipboard;
+		procedure Undo;
+		procedure Redo;
+		procedure ClearUndo;
+		procedure ClearRedo;
+		procedure ScrollCaret; virtual;
+		procedure ChangeIndent(Change: Integer); virtual;
+		procedure RemoveTrSp; virtual;
+		procedure RemoveTrSpFromLine(LineIdx: Integer); virtual;
+		procedure RemoveTrSpFromString(var Str: string; IncludeLastLine: Boolean = False); virtual;
+		property Text: TCaption read FText write SetText;
+		property TextLength: Integer read FTextLength;
+		property TrackedRanges: TMCRanges read FTrackedRanges;
+		property WholeText: TCustomRange read FWholeText;
+		property LineCount: Integer read GetLineCount;
+		property LongestLineLength: Integer read FLongestLineLength;
+		property LineLength[LineIndex: Integer]: Integer read GetLineLength;
+		property VisualLineLength[LineIndex: Integer]: Integer read GetVisualLineLength;
+		property VisibleRange: TVisibleRange read FVisibleRange;
+		property Selection: TSelectionRange read FSelection;
+		property SelStart: Integer read GetSelStart write SetSelStart;
+		property SelLength: Integer read GetSelLength write SetSelLength;
+		property ForbiddenFontStyles: TFontStyles read FForbiddenFontStyles;
+		property CanUndo: Boolean read GetCanUndo;
+		property CanRedo: Boolean read GetCanRedo;
+		property DrawingSuspended: Boolean read FDrawingSuspended write FDrawingSuspended;
+		property OnReplaceText: TReplaceEvent read FOnReplaceText write FOnReplaceText;
+		property OnChangePrivate: TNotifyEvent read FOnChangePrivate write FOnChangePrivate;
+	published
+		property ScrollBars: TScrollStyle read FScrollBars write SetScrollBars default ssNone;
+		property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
+		property Bitmapped: Boolean read FBitmapped write SetBitmapped;
+		property ReadOnly: Boolean read FReadOnly write SetReadOnly default False;
+		property AllowUndo: Boolean read FAllowUndo write SetAllowUndo default True;
+		property OnChange: TNotifyEvent read FOnChange write FOnChange;
+		property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
+		property Lines: TStrings read FLines write SetLines;
+		property AlwaysShowCaret: Boolean read FAlwaysShowCaret write SetAlwaysShowCaret;
+		property LeftMargin: Integer read FLeftMargin write SetLeftMargin;
+		property TopMargin: Integer read FTopMargin write SetTopMargin;
+		property TabSize: Integer read FTabSize write SetTabSize;
+		property AutoIndent: Boolean read FAutoIndent write FAutoIndent;
+		property DragDropEditing: Boolean read FDragDropEditing write FDragDropEditing;
+		property RemoveTrailingSpaces: Boolean read FRemoveTrailingSpaces write SetRemoveTrailingSpaces;
+		property TabStop default True;
+		property Align;
+		property Anchors;
+		property Color nodefault;
+		property Constraints;
+		property Ctl3D;
+		property Enabled;
+		property Font;
+		property ParentColor;
+		property ParentCtl3D;
+		property ParentFont;
+		property ParentShowHint;
+		property PopupMenu;
+		property ShowHint;
+		property TabOrder;
+		property Visible;
+		property OnClick;
+		property OnDblClick;
+		property OnEnter;
+		property OnExit;
+		property OnKeyDown;
+		property OnKeyPress;
+		property OnKeyUp;
+		property OnMouseDown;
+		property OnMouseMove;
+		property OnMouseUp;
+	end;
+
+	TCustomRange = class(TFastContainerItem)
+	private
+		FEditor: TMemoComponent;
+		FChanging: Integer;
+		FOnOverwrite: TNotifyEvent;
+		FOnChange: TNotifyEvent;
+		function GetEndPoint: TPoint;
+		function GetStartPoint: TPoint;
+	protected
+		procedure SetRStart(const Value: Integer); virtual;
+		procedure SetREnd(const Value: Integer); virtual;
+		procedure SetRLength(const Value: Integer); virtual;
+		function GetRStart: Integer; virtual; abstract;
+		function GetREnd: Integer; virtual; abstract;
+		function GetRLength: Integer; virtual;
+		function GetEndRowCol: TTextCell; virtual;
+		function GetStartRowCol: TTextCell; virtual;
+		procedure SetEndRowCol(const Value: TTextCell); virtual;
+		procedure SetStartRowCol(const Value: TTextCell); virtual;
+		procedure SetText(const Value: string); virtual;
+		function GetText: string; virtual;
+		procedure Changing; dynamic;
+		procedure Change; dynamic;
+		procedure DiscardChanges; dynamic;
+		procedure InternalDoMove(RangeStart, RangeEnd, LC: Integer); virtual;
+	public
+		constructor Create(Collection: TFastObjectContainer); override;
+		procedure AssignTo(Dest: TPersistent); override;
+		procedure NotifyOverwrite; dynamic;
+		procedure DoChanging;
+		procedure DoChange;
+		procedure DoDiscardChanges;
+		procedure Clear; virtual;
+		function CharInRange(CharIdx: Integer): Boolean;
+		procedure DrawRange; virtual;
+		procedure ScrollInView(FromBorder: Integer); virtual;
+		property Editor: TMemoComponent read FEditor write FEditor;
+		property StartRowCol: TTextCell read GetStartRowCol write SetStartRowCol;
+		property EndRowCol: TTextCell read GetEndRowCol write SetEndRowCol;
+		property StartPoint: TPoint read GetStartPoint;
+		property EndPoint: TPoint read GetEndPoint;
+		property Text: string read GetText write SetText;
+	published
+		property RStart: Integer read GetRStart write SetRStart;
+		property REnd: Integer read GetREnd write SetREnd;
+		property RLength: Integer read GetRLength write SetRLength;
+		property OnChange: TNotifyEvent read FOnChange write FOnChange;
+		property OnOverwrite: TNotifyEvent read FOnOverwrite write FOnOverwrite;
+	end;
+
+	TMCRange = class(TCustomRange)
+	private
+		FRStart: Integer;
+		FREnd: Integer;
+	protected
+		procedure SetREnd(const Value: Integer); override;
+		procedure SetRStart(const Value: Integer); override;
+		function GetREnd: Integer; override;
+		function GetRStart: Integer; override;
+		procedure InternalDoMove(RangeStart, RangeEnd, LC: Integer); override;
+	public
+		constructor Create(Collection: TFastObjectContainer); override;
+	end;
+
+	TWholeTextRange = class(TCustomRange)
+	protected
+		function GetREnd: Integer; override;
+		function GetRStart: Integer; override;
+	end;
+
+	TVisibleRange = class(TCustomRange)
+	private
+		FLeftCol: Integer;
+		FTopRow: Integer;
+		procedure SetLeftCol(const Value: Integer);
+		procedure SetRightCol(const Value: Integer);
+		function GetRightCol: Integer;
+		procedure SetTopRow(const Value: Integer);
+		procedure SetBottomRow(const Value: Integer);
+		function GetBottomRow: Integer;
+	protected
+		VisibleTextRect: TRect;
+		procedure SetRStart(const Value: Integer); override;
+		procedure SetREnd(const Value: Integer); override;
+		procedure SetRLength(const Value: Integer); override;
+		function GetRStart: Integer; override;
+		function GetREnd: Integer; override;
+		function GetStartRowCol: TTextCell; override;
+		function GetEndRowCol: TTextCell; override;
+		procedure SetStartRowCol(const Value: TTextCell); override;
+		procedure SetEndRowCol(const Value: TTextCell); override;
+		procedure Changing; override;
+		procedure Change; override;
+		procedure Update;
+	public
+		constructor Create(Collection: TFastObjectContainer); override;
+	published
+		property LeftCol: Integer read FLeftCol write SetLeftCol;
+		property RightCol: Integer read GetRightCol write SetRightCol;
+		property TopRow: Integer read FTopRow write SetTopRow;
+		property BottomRow: Integer read GetBottomRow write SetBottomRow;
+	end;
+
+	TSelectWordDirection = (swLeft, swRight);
+	TSelectWordDirections = set of TSelectWordDirection;
+	TSelectionRange = class(TMCRange)
+	private
+		FOldSel: TCustomRange;
+		FBackwards: Boolean;
+		FCaretShowing: Boolean;
+		FScrCol: Integer;
+		function GetCursorPos: Integer;
+		procedure SetCursorPos(const Value: Integer);
+		function GetScrCol: Integer;
+	protected
+		procedure Changing; override;
+		procedure Change; override;
+		procedure DiscardChanges; override;
+		procedure SetText(const Value: string); override;
+	public
+		procedure AssignTo(Dest: TPersistent); override;
+		procedure NoSelAtPos(Pos: Integer);
+		procedure UpdateCaretPos;
+		procedure ShowCaret;
+		procedure HideCaret;
+		procedure SelectWord(Directions: TSelectWordDirections = [swLeft, swRight]);
+		function ScrColToCol(Row: Integer): Integer;
+		property CursorPos: Integer read GetCursorPos write SetCursorPos;
+		property ScrCol: Integer read GetScrCol write FScrCol;
+	published
+		property Backwards: Boolean read FBackwards write FBackwards;
+	end;
+
+	TCustomFormattedRange = class(TMCRange)
+	protected
+		function GetColor: TColor; virtual; abstract;
+		function GetFont: TFont; virtual; abstract;
+		procedure SetColor(const Value: TColor); virtual;
+		procedure SetFont(const Value: TFont); virtual;
+	public
+		FreeWhenDone: Boolean;
+		procedure AssignTo(Dest: TPersistent); override;
+		procedure CleanUpFont; virtual;
+	published
+		property Color: TColor read GetColor write SetColor;
+		property Font: TFont read GetFont write SetFont;
+	end;
+
+	TFormattedRange = class(TCustomFormattedRange)
+	private
+		FFont: TFont;
+		FColor: TColor;
+	protected
+		function GetColor: TColor; override;
+		function GetFont: TFont; override;
+		procedure SetColor(const Value: TColor); override;
+		procedure SetFont(const Value: TFont); override;
+	public
+		constructor Create(Collection: TFastObjectContainer); override;
+		destructor Destroy; override;
+	end;
+
+	TNormalFormattedRange = class(TCustomFormattedRange)
+	protected
+		function GetColor: TColor; override;
+		function GetFont: TFont; override;
+	end;
+
+	TRangeClass = class of TCustomRange;
+
+	TMCRanges = class(TFastObjectContainer)
+	private
+		FItemClass: TRangeClass;
+		function NewGetOwner: TMemoComponent;
+	protected
+		function NewGetItem(ItemIndex: Integer): TCustomRange;
+	public
+		FDestroying: Boolean;
+		constructor Create(AOwner: TMemoComponent);
+		destructor Destroy; override;
+		function Add: TCustomRange; overload;
+		function Add(Start, Count: Integer): TCustomRange; overload;
+		property ItemClass: TRangeClass read FItemClass write FItemClass;
+		property Items[ItemIndex: Integer]: TCustomRange read NewGetItem;
+		property Owner: TMemoComponent read NewGetOwner;
+	end;
+
+	TIntegerList = class(TObject)
+	private
+		FList: TList;
+		function GetCount: Integer;
+		function GetItem(ItemIndex: Integer): Integer;
+		procedure SetItem(ItemIndex: Integer; const Value: Integer);
+		procedure SetCount(const Value: Integer);
+	public
+		constructor Create;
+		destructor Destroy; override;
+		function Add(Item: Integer): Integer;
+		procedure Insert(Index: Integer; Item: Integer);
+		procedure Delete(Index: Integer);
+		procedure Clear; dynamic;
+		property Items[ItemIndex: Integer]: Integer read GetItem write SetItem;
+		property Count: Integer read GetCount write SetCount;
+	end;
+
+function TextCell(CellRow, CellCol: Integer): TTextCell;
+
+procedure Register;
+
+implementation
+
+uses
+	UtilsDos, ClipBrd;
+
+const
+	MaxScrollTolerance = 2;
+	ScrollOffset = 10;
+
+procedure Register;
+begin
+	RegisterComponents('Edit Controls', [TMemoComponent]);
+end;
+
+{ TMemoComponentStrings Definition }
+
+type
+	TMemoComponentStrings = class(TStrings)
+	private
+		Memo: TMemoComponent;
+	protected
+		function Get(LineIndex: Integer): string; override;
+		function GetCount: Integer; override;
+		function GetTextStr: string; override;
+		procedure Put(LineIndex: Integer; const S: string); override;
+		procedure SetTextStr(const Value: string); override;
+	public
+		procedure Clear; override;
+		procedure Delete(LineIndex: Integer); override;
+		procedure Insert(LineIndex: Integer; const S: string); override;
+	end;
+
+{ Helper Functions }
+
+function TextCell(CellRow, CellCol: Integer): TTextCell;
+begin
+	with Result do begin
+		Row := CellRow;
+		Col := CellCol;
+	end;
+end;
+
+{ TMemoComponent }
+
+procedure TMemoComponent.CancelDragging;
+var
+	P: TPoint;
+begin
+	if FSelecting or FDragging then begin
+		if HandleAllocated then
+			KillTimer (Handle, 1);
+		FSelecting := False;
+		FDragging := False;
+		P := ScreenToClient (Mouse.CursorPos);
+		MouseMoveInternal (P.X, P.Y);
+	end;
+end;
+
+procedure TMemoComponent.CellFromScrCol(var Cell: TTextCell);
+var
+	I,
+	Col,
+	Count: Integer;
+begin
+	if Cell.Row < 1 then
+		Cell.Row := 1;
+	if Cell.Row > LineCount then
+		Cell.Row := LineCount;
+	if TabSize <> 1 then begin
+		Count := 0;
+		I := CellToCharIdx (TextCell (Cell.Row, 1));
+		Col := Cell.Col;
+		Cell.Col := 1;
+		while Count < Col do begin
+			if (I <= TextLength) and (Text [I] = #9) then
+				Count := (Count div TabSize + 1) * TabSize
+			else
+				Inc (Count);
+			if Count < Col then begin
+				Inc (I);
+				Inc (Cell.Col);
+			end;
+		end;
+	end;
+	if Cell.Col < 1 then
+		Cell.Col := 1;
+	if Cell.Col > LineLength [Cell.Row] + 1 then
+		Cell.Col := LineLength [Cell.Row] + 1;
+end;
+
+function TMemoComponent.CellFromScrColToScrCol(var Cell: TTextCell):
+	Integer;
+var
+	I,
+	Col,
+	Count: Integer;
+begin
+	if Cell.Row < 1 then
+		Cell.Row := 1;
+	if Cell.Row > LineCount then
+		Cell.Row := LineCount;
+	if TabSize = 1 then
+		Result := Cell.Col
+	else begin
+		Result := 1;
+		Count := 0;
+		I := CellToCharIdx (TextCell (Cell.Row, 1));
+		Col := Cell.Col;
+		Cell.Col := 1;
+		while Count < Col do begin
+			Result := Count + 1;
+			if (I <= TextLength) and (Text [I] = #9) then
+				Count := (Count div TabSize + 1) * TabSize
+			else
+				Inc (Count);
+			if Count < Col then begin
+				Inc (I);
+				Inc (Cell.Col);
+			end;
+		end;
+	end;
+	if Cell.Col < 1 then
+		Cell.Col := 1;
+	if Cell.Col > LineLength [Cell.Row] + 1 then
+		Cell.Col := LineLength [Cell.Row] + 1;
+end;
+
+function TMemoComponent.CellToCharIdx(Cell: TTextCell): Integer;
+begin
+	with Cell do
+		if Row <= 0 then
+			Result := Col
+		else if Row > LineCount then
+			Result := TextLength + 2 + Col
+		else
+			Result := FLineStarts.Items [Row - 1] + Col - 1;
+end;
+
+function TMemoComponent.CellToScrCol(Cell: TTextCell): Integer;
+var
+	I,
+	Idx: Integer;
+begin
+	if TabSize = 1 then
+		Result := Cell.Col
+	else begin
+		Result := 0;
+		Idx := CellToCharIdx (TextCell (Cell.Row, 1));
+		for I := Idx to Idx + Cell.Col - 2 do begin
+			if (I > 0) and (I <= TextLength) and (Text [I] = #9) then
+				Result := (Result div TabSize + 1) * TabSize
+			else
+				Inc (Result);
+		end;
+		Inc (Result);
+	end;
+end;
+
+procedure TMemoComponent.Change;
+begin
+	if not DontNotify then begin
+		inherited Changed;
+		if Assigned (FOnChange) then
+			FOnChange (Self);
+		if Assigned (FOnChangePrivate) then
+			FOnChangePrivate (Self);
+	end;
+end;
+
+procedure TMemoComponent.ChangeIndent(Change: Integer);
+var
+	I,
+	RS,
+	RE,
+	L,
+	CurPos: Integer;
+begin
+	if Change <> 0 then begin
+		DontNotify := True;
+		try
+			VisibleRange.DoChanging;
+			try
+				MakeUndoOperation (CreateUndoBeginEndBlock);
+				RS := Selection.StartRowCol.Row;
+				RE := Selection.EndRowCol.Row;
+				if RE < RS then
+					RE := RS;
+				for I := RS to RE do begin
+					CurPos := CellToCharIdx (TextCell (I, 1));
+					if Change > 0 then begin
+						while (CurPos <= TextLength) and (Text [CurPos] in [#9, #21]) do
+							Inc (CurPos);
+						L := Change;
+						with TMCRange.Create (nil) do begin
+							Editor := Self;
+							RStart := CurPos;
+							RLength := 0;
+							Text := StringOfChar (#9, L);
+							if (Selection.RLength > 0) and (Selection.RStart = REnd + 1) then
+								Selection.RStart := RStart;
+							Free;
+						end;
+					end else begin
+						L := 0;
+						while (CurPos <= TextLength) and (Text [CurPos] in [#9, #21]) do begin
+							Inc (CurPos);
+							Inc (L);
+						end;
+						if L > -Change then
+							L := -Change;
+						with TMCRange.Create (nil) do begin
+							Editor := Self;
+							RStart := CurPos - L;
+							REnd := CurPos - 1;
+							Text := '';
+							Free;
+						end;
+					end;
+				end;
+				MakeUndoOperation (CreateUndoBeginEndBlock);
+			finally
+				VisibleRange.DoDiscardChanges;
+			end;
+			Selection.HideCaret;
+			try
+				VisibleRange.DrawRange;
+				Selection.UpdateCaretPos;
+			finally
+				Selection.ShowCaret;
+			end;
+		finally
+			DontNotify := False;
+		end;
+		Self.Change;
+		SelectionChange;
+	end;
+end;
+
+function TMemoComponent.CharIdxToCell(CharIdx: Integer): TTextCell;
+var
+	LineIdx: Integer;
+begin
+	with FLineStarts do begin
+		if TextLength > 0 then
+			LineIdx := Count * CharIdx div TextLength - 1
+		else
+			LineIdx := 0;
+		if LineIdx < 0 then
+			LineIdx := 0;
+		if LineIdx >= Count then
+			LineIdx := Count - 1;
+		while (LineIdx < Count - 1) and (Items [LineIdx] < CharIdx) do
+			Inc (LineIdx);
+		while (LineIdx > 0) and (Items [LineIdx] > CharIdx) do
+			Dec (LineIdx);
+		with Result do begin
+			Row := LineIdx + 1;
+			Col := CharIdx - Items [LineIdx] + 1;
+		end;
+	end;
+end;
+
+procedure TMemoComponent.Clear;
+begin
+	Text := '';
+end;
+
+procedure TMemoComponent.ClearRedo;
+begin
+	while CanRedo do
+		GetLastRedo;
+end;
+
+procedure TMemoComponent.ClearSelection;
+begin
+	Perform (wm_Clear, 0, 0);
+end;
+
+procedure TMemoComponent.ClearUndo;
+begin
+	while CanRedo do
+		GetLastRedo;
+	while CanUndo do
+		GetLastUndo;
+	Change;
+end;
+
+procedure TMemoComponent.CMFontChanged(var Message: TMessage);
+begin
+	inherited;
+	UpdateFontSize;
+	VisibleRange.Update;
+	VisibleRange.DrawRange;
+end;
+
+procedure TMemoComponent.CMMouseWheel(var Message: TCMMouseWheel);
+var
+	Msg: TWMScroll;
+	I: Integer;
+begin
+	with Msg do begin
+		Msg := wm_VScroll;
+		if Message.WheelDelta >= 0 then
+			ScrollCode := sb_LineUp
+		else
+			ScrollCode := sb_LineDown;
+	end;
+	for I := 1 to 3 do
+		WMVScroll (Msg);
+	Message.Result := 1;
+end;
+
+procedure TMemoComponent.CMWantSpecialKey(var Message: TCMWantSpecialKey);
+begin
+	inherited;
+	if not (csDesigning in ComponentState) then
+		if Message.CharCode in [vk_Left, vk_Right, vk_Up, vk_Down, vk_Prior, vk_Next, vk_Home, vk_End, vk_Tab, vk_Clear, vk_Delete, vk_Insert, vk_Return] then
+			Message.Result := 1;
+end;
+
+procedure TMemoComponent.CopyToClipboard;
+begin
+	Perform (wm_Copy, 0, 0);
+end;
+
+constructor TMemoComponent.Create(AOwner: TComponent);
+begin
+	inherited;
+	FBitmapped := False;
+	FText := '';
+	FLineStarts := TIntegerList.Create;
+	FLineStarts.Add (1);
+	FLines := TMemoComponentStrings.Create;
+	TMemoComponentStrings(FLines).Memo := Self;
+	FTrackedRanges := TMCRanges.Create (Self);
+	FWholeText := TWholeTextRange.Create (nil);
+	FWholeText.Editor := Self;
+	FVisibleRange := TVisibleRange.Create (TrackedRanges);
+	FSelection := TSelectionRange.Create (TrackedRanges);
+	with FSelection do begin
+		FRStart := 1;
+		FREnd := 0;
+	end;
+	FTabSize := 2;
+	FScrollBars := ssBoth;
+	FBorderStyle := bsSingle;
+	FLeftMargin := 2;
+	FTopMargin := 0;
+	FAllowUndo := True;
+	ControlStyle := ControlStyle + [csOpaque] - [csNoStdEvents];
+	DoubleBuffered := False;
+	Constraints.MinWidth := 64;
+	Constraints.MinHeight := 64;
+	TabStop := True;
+	ParentColor := False;
+	Color := clWindow;
+	Font.Name := 'Courier New';
+	Font.Size := 10;
+	Width := 129;
+	Height := 129;
+end;
+
+procedure TMemoComponent.CreateParams(var Params: TCreateParams);
+const
+	ScrollBar: array [TScrollStyle] of DWORD = (0, WS_HSCROLL, WS_VSCROLL,
+		WS_HSCROLL or WS_VSCROLL);
+begin
+	inherited;
+	with Params do begin
+		Style := Style or ScrollBar [FScrollBars];
+		if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then begin
+			Style := Style and not WS_BORDER;
+			ExStyle := ExStyle or WS_EX_CLIENTEDGE;
+		end;
+	end;
+end;
+
+function TMemoComponent.CreateSplitRanges(Range: TCustomRange): TFormattedRangeArray;
+var
+	RS,
+	RE: Integer;
+begin
+	RS := Range.RStart;
+	if Selection.RLength > 0 then begin
+		RE := Selection.RStart - 1;
+		if RE > Range.REnd then
+			RE := Range.REnd;
+		if RE >= RS then begin
+			SetLength (Result, Length (Result) + 1);
+			Result [High (Result)] := TNormalFormattedRange.Create (nil);
+			with Result [High (Result)] do begin
+				FreeWhenDone := True;
+				Editor := Self;
+				RStart := RS;
+				REnd := RE;
+			end;
+		end;
+		RS := Selection.RStart;
+		if RS < Range.RStart then
+			RS := Range.RStart;
+		RE := Selection.REnd;
+		if RE > Range.REnd then
+			RE := Range.REnd;
+		if RE >= RS then begin
+			SetLength (Result, Length (Result) + 1);
+			Result [High (Result)] := TFormattedRange.Create (nil);
+			with Result [High (Result)] do begin
+				FreeWhenDone := True;
+				Editor := Self;
+				RStart := RS;
+				REnd := RE;
+				Font.Assign (Self.Font);
+				if HasFocus then begin
+					Font.Color := clHighlightText;
+					Color := clHighlight;
+				end else
+					Color := clSilver;
+			end;
+		end;
+		RS := Selection.REnd + 1;
+		if RS < Range.RStart then
+			RS := Range.RStart;
+	end;
+	RE := Range.REnd;
+	if RE >= RS then begin
+		SetLength (Result, Length (Result) + 1);
+		Result [High (Result)] := TNormalFormattedRange.Create (nil);
+		with Result [High (Result)] do begin
+			FreeWhenDone := True;
+			Editor := Self;
+			RStart := RS;
+			REnd := RE;
+		end;
+	end;
+end;
+
+function TMemoComponent.CreateUndoBeginEndBlock: PUndoOperation;
+begin
+	New (Result);
+	with Result^ do begin
+		RStart := -1;
+		REnd := -1;
+		NewText := '';
+	end;
+end;
+
+procedure TMemoComponent.CreateWnd;
+begin
+	inherited;
+	UpdateFontSize;
+	SetCurCursor (ccIBeam);
+end;
+
+procedure TMemoComponent.CutToClipboard;
+begin
+	Perform (wm_Cut, 0, 0);
+end;
+
+procedure TMemoComponent.DblClick;
+begin
+	inherited;
+	FDblClicked := True;
+	Selection.SelectWord;
+end;
+
+destructor TMemoComponent.Destroy;
+begin
+	DontNotify := True;
+	FHasFocus := False;
+	ClearUndo;
+	FSelection.Free;
+	FVisibleRange.Free;
+	FLines.Free;
+	FTrackedRanges.Free;
+	FWholeText.Free;
+	FLineStarts.Free;
+	if Assigned (DrawBmp) then begin
+		DrawBmp.Free;
+		DrawBmp := nil;
+	end;
+	FreeCaret;
+	inherited;
+end;
+
+procedure TMemoComponent.DrawBorder(LeftRect, TopRect: TRect;
+  Canvas: TCanvas);
+begin
+	Canvas.Brush.Color := Color;
+	Canvas.FillRect (LeftRect);
+	Canvas.FillRect (TopRect);
+end;
+
+procedure TMemoComponent.DrawTextLine(Range: TCustomRange; Left, Top: Integer; NextTabStop: Integer);
+var
+	I,
+	SP,
+	X,
+	Y,
+	TextFlags: Integer;
+	R: TRect;
+	Ranges: TFormattedRangeArray;
+	S: string;
+	Cnv: TCanvas;
+begin
+	if HandleAllocated and ((Range.RLength > 0) or (Range.REnd >= TextLength)) then begin
+		if Bitmapped then begin
+			Cnv := DrawBmp.Canvas;
+			TextFlags := eto_Opaque or eto_Clipped;
+		end else begin
+			Cnv := Canvas;
+			TextFlags := eto_Opaque or eto_Clipped;
+		end;
+		SetLength (Ranges, 0);
+		Ranges := CreateSplitRanges (Range);
+		R := Rect (Left, Top, Left, Top + FontHeight);
+		for I := Low (Ranges) to High (Ranges) do
+			with Ranges [I] do begin
+				CleanUpFont;
+				if RLength > 0 then begin
+					Cnv.Brush.Color := Color;
+					Cnv.Font.Assign (Font);
+					if Self.Text [REnd] = #10 then
+						S := Copy (Self.Text, RStart, RLength - 2)
+					else if Self.Text [REnd] = #13 then
+						S := Copy (Self.Text, RStart, RLength - 1)
+					else
+						S := Copy (Self.Text, RStart, RLength);
+					SP := 1;
+					while SP <= Length (S) do begin
+						if S [SP] = #9 then begin
+							System.Delete (S, SP, 1);
+							System.Insert (StringOfChar (' ', NextTabStop), S, SP);
+							Inc (SP, NextTabStop);
+							NextTabStop := TabSize;
+						end else begin
+							Inc (SP);
+							Dec (NextTabStop);
+							if NextTabStop <= 0 then
+								Inc (NextTabStop, TabSize);
+						end;
+					end;
+					if (REnd <= TextLength) and (Self.Text [REnd] in [#10, #13]) then begin
+						R.Right := ClientWidth;
+					end else
+						R.Right := R.Left + FontWidth * Length (S);
+					X := R.Left;
+					Y := R.Top;
+					if (fsItalic in Font.Style) and (Pos ('Courier', Font.Name) > 0) then
+						Dec (Y);
+					if R.Left < LeftMargin then
+						R.Left := LeftMargin;
+					if R.Right > R.Left then begin
+						{$IFDEF DrawDebug}
+							Cnv.FillRect (R);
+							Cnv.DrawFocusRect (R);
+							Sleep (100);
+						{$ENDIF}
+						ExtTextOut (Cnv.Handle, X, Y, TextFlags, @R, PChar (S), Length (S), nil);
+					end;
+					R.Left := R.Right;
+				end;
+				if FreeWhenDone then
+					Free;
+			end;
+		if Range.REnd >= TextLength then begin
+			if R.Left < LeftMargin then
+				R.Left := LeftMargin;
+			R.Right := ClientWidth;
+			Cnv.Brush.Color := Color;
+			Cnv.FillRect (R);
+		end;
+	end;
+end;
+
+procedure TMemoComponent.EMCanUndo(var Message: TMessage);
+begin
+	if Message.WParam = 1 then
+		Message.Result := Integer (Assigned (FRedoStack))
+	else
+		Message.Result := Integer (Assigned (FUndoStack));
+end;
+
+procedure TMemoComponent.EMUndo(var Message: TMessage);
+var
+	Op: TUndoOperation;
+	NewOp: PUndoOperation;
+	Repeating: Boolean;
+	CurSel: TMCRange;
+begin
+	if Perform (em_CanUndo, Message.WParam, 0) <> 0 then
+		with Message do begin
+			FInUndo := True;
+			Repeating := False;
+			CurSel := nil;
+			repeat
+				if WParam = 1 then
+					Op := GetLastRedo
+				else
+					Op := GetLastUndo;
+				if IsUndoBeginEndBlock (@Op) then begin
+					Repeating := not Repeating;
+					if Repeating then begin
+						DontNotify := True;
+						VisibleRange.DoChanging;
+					end else begin
+						VisibleRange.DoDiscardChanges;
+						Selection.HideCaret;
+						VisibleRange.DrawRange;
+						if Assigned (CurSel) then
+							Selection.Assign (CurSel);
+						Selection.UpdateCaretPos;
+						Selection.ShowCaret;
+						DontNotify := False;
+						Self.Change;
+						SelectionChange;
+						Selection.ScrollInView (4);
+					end;
+					if WParam = 1 then
+						MakeUndoOperation (CreateUndoBeginEndBlock)
+					else
+						MakeRedoOperation (CreateUndoBeginEndBlock);
+				end else begin
+					with TMCRange.Create (nil) do begin
+						Editor := Self;
+						New (NewOp);
+						RStart := Op.RStart;
+						REnd := Op.REnd;
+						NewOp.NewText := Text;
+						Text := Op.NewText;
+						NewOp.RStart := RStart;
+						NewOp.REnd := REnd;
+						if WParam = 1 then
+							MakeUndoOperation (NewOp)
+						else
+							MakeRedoOperation (NewOp);
+						if Repeating then begin
+							if Assigned (CurSel) then begin
+								if REnd + 1 > CurSel.RStart then
+									CurSel.RStart := REnd + 1;
+							end else begin
+								CurSel := TMCRange.Create (TrackedRanges);
+								CurSel.RStart := REnd + 1;
+							end;
+						end else begin
+							AssignTo (Selection);
+							Selection.ScrollInView (4);
+						end;
+						Free;
+					end;
+				end;
+			until not Repeating;
+			if Assigned (CurSel) then
+				CurSel.Free;
+			FInUndo := False;
+			Change;
+		end;
+end;
+
+procedure TMemoComponent.FreeCaret;
+begin
+	if FCaretCreated then begin
+		Selection.HideCaret;
+		DestroyCaret;
+		FCaretCreated := False;
+	end;
+end;
+
+function TMemoComponent.GetCanRedo: Boolean;
+begin
+	Result := Perform (em_CanUndo, 1, 0) <> 0;
+end;
+
+function TMemoComponent.GetCanUndo: Boolean;
+begin
+	Result := Perform (em_CanUndo, 0, 0) <> 0;
+end;
+
+function TMemoComponent.GetLastRedo: TUndoOperation;
+begin
+	if Assigned (FRedoStack) then begin
+		Result := FRedoStack^;
+		Dispose (FRedoStack);
+		FRedoStack := Result.NextItem;
+	end;
+end;
+
+function TMemoComponent.GetLastUndo: TUndoOperation;
+begin
+	if Assigned (FUndoStack) then begin
+		Result := FUndoStack^;
+		Dispose (FUndoStack);
+		FUndoStack := Result.NextItem;
+	end;
+end;
+
+function TMemoComponent.GetLineCount: Integer;
+begin
+	Result := FLineStarts.Count;
+end;
+
+function TMemoComponent.GetLineLength(LineIndex: Integer): Integer;
+begin
+	Result := CellToCharIdx (TextCell (LineIndex + 1, 0)) - CellToCharIdx (TextCell (LineIndex, 0)) - 2;
+end;
+
+function TMemoComponent.GetSelLength: Integer;
+begin
+	Result := Selection.RLength;
+end;
+
+function TMemoComponent.GetSelStart: Integer;
+begin
+	Result := Selection.RStart - 1;
+end;
+
+function TMemoComponent.GetVisualLineLength(LineIndex: Integer): Integer;
+begin
+	Result := CellToScrCol (TextCell (LineIndex, GetLineLength (LineIndex) + 1)) - 1;
+end;
+
+procedure TMemoComponent.HandleKeyDown(var Key: Word; Shift: TShiftState);
+var
+	NewPos: Integer;
+	Cell: TTextCell;
+	SavScrCol: Integer;
+	InWord: Boolean;
+	P: TPoint;
+begin
+	inherited;
+	SavScrCol := -1;
+	NewPos := Low (Integer);
+	if ReadOnly then begin
+		case Key of
+			vk_Left: Perform (wm_HScroll, sb_LineLeft, 0);
+			vk_Right: Perform (wm_HScroll, sb_LineRight, 0);
+			vk_Up: Perform (wm_VScroll, sb_LineUp, 0);
+			vk_Down: Perform (wm_VScroll, sb_LineDown, 0);
+			vk_Prior: Perform (wm_VScroll, sb_PageUp, 0);
+			vk_Next: Perform (wm_VScroll, sb_PageDown, 0);
+			vk_Home: begin
+				if ssCtrl in Shift then
+					Perform (wm_VScroll, sb_Top, 0);
+				Perform (wm_HScroll, sb_Top, 0);
+			end;
+			vk_End:
+				if ssCtrl in Shift then
+					Perform (wm_VScroll, sb_Bottom, 0)
+				else
+					Perform (wm_HScroll, sb_Bottom, 0);
+			vk_Insert:
+				if Shift = [ssCtrl] then
+					CopyToClipboard;
+		end;
+	end else begin
+		with Selection do begin
+			case Key of
+				vk_Clear: begin
+					Clear;
+					ScrollInView (4);
+				end;
+				vk_Delete:
+					if (Shift = []) or (Shift = [ssCtrl]) then begin
+						if (RLength = 0) or (Shift = [ssCtrl]) then begin
+							DoChanging;
+							if Shift = [ssCtrl] then
+								SelectWord ([swRight]);
+							if RLength = 0 then begin
+								RLength := 1;
+								if (RLength = 1) and (Text [1] in [#10, #13]) then
+									RLength := 2;
+							end;
+							DoDiscardChanges;
+						end;
+						Clear;
+						ScrollInView (4);
+					end else if Shift = [ssShift] then
+						CutToClipboard;
+				vk_Insert:
+					if Shift = [ssShift] then
+						PasteFromClipboard
+					else if Shift = [ssCtrl] then
+						CopyToClipboard;
+				vk_Back:
+					if (Shift = []) or (Shift = [ssShift]) or (Shift = [ssCtrl]) then begin
+						if (RLength = 0) or (Shift = [ssCtrl]) then begin
+							DoChanging;
+							if Shift = [ssCtrl] then
+								SelectWord ([swLeft]);
+							if RLength = 0 then begin
+								RStart := RStart - 1;
+								if (RLength = 1) and (Text [1] in [#10, #13]) then
+									RStart := RStart - 1;
+							end;
+							DoDiscardChanges;
+						end;
+						Clear;
+						ScrollInView (4);
+					end else if Shift = [ssAlt] then
+						Undo
+					else if Shift = [ssAlt, ssShift] then
+						Redo;
+				vk_Tab:
+					if Shift = [] then begin
+						Text := #9;
+						ScrollInView (4);
+					end;
+				vk_Left: begin
+					if (not (ssShift in Shift)) and (RLength > 0) and (not AlwaysShowCaret) then
+						REnd := RStart - 1
+					else
+						if (ssCtrl in Shift) then begin
+							NewPos := CursorPos;
+							InWord := (NewPos > 1) and (NewPos <= TextLength + 1) and (Self.Text [NewPos - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
+							while (NewPos > 1) and ((Self.Text [NewPos - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '_']) = InWord) do begin
+								if Self.Text [NewPos - 1] in [#10, #13] then
+									Dec (NewPos, 2)
+								else
+									Dec (NewPos);
+							end;
+						end else begin
+							if (CursorPos > 1) and (Self.Text [CursorPos - 1] in [#10, #13]) then
+								NewPos := CursorPos - 2
+							else
+								NewPos := CursorPos - 1;
+						end;
+				end;
+				vk_Right: begin
+					if (not (ssShift in Shift)) and (RLength > 0) and (not AlwaysShowCaret) then
+						RStart := REnd + 1
+					else
+						if (ssCtrl in Shift) then begin
+							NewPos := CursorPos;
+							InWord := (NewPos >= 1) and (NewPos <= TextLength) and (Self.Text [NewPos] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
+							while (NewPos <= TextLength) and ((Self.Text [NewPos] in ['A'..'Z', 'a'..'z', '0'..'9', '_']) = InWord) do begin
+								if Self.Text [NewPos] in [#10, #13] then
+									Inc (NewPos, 2)
+								else
+									Inc (NewPos);
+							end;
+						end else begin
+							if (CursorPos <= TextLength) and (Self.Text [CursorPos] in [#10, #13]) then
+								NewPos := CursorPos + 2
+							else
+								NewPos := CursorPos + 1;
+						end;
+				end;
+				vk_Up: begin
+					if (not (ssShift in Shift)) and (RLength > 0) and (not AlwaysShowCaret) then
+						REnd := RStart - 1
+					else begin
+						SavScrCol := ScrCol;
+						Cell := CharIdxToCell (CursorPos);
+						Dec (Cell.Row);
+						Cell.Col := ScrColToCol (Cell.Row);
+						NewPos := CellToCharIdx (Cell);
+					end;
+				end;
+				vk_Down: begin
+					if (not (ssShift in Shift)) and (RLength > 0) and (not AlwaysShowCaret) then
+						RStart := REnd + 1
+					else begin
+						SavScrCol := ScrCol;
+						Cell := CharIdxToCell (CursorPos);
+						Inc (Cell.Row);
+						Cell.Col := ScrColToCol (Cell.Row);
+						NewPos := CellToCharIdx (Cell);
+					end;
+				end;
+				vk_Prior: begin
+					SavScrCol := ScrCol;
+					Cell := CharIdxToCell (CursorPos);
+					Dec (Cell.Row, PageHeight - 1);
+					Cell.Col := ScrColToCol (Cell.Row);
+					NewPos := CellToCharIdx (Cell);
+				end;
+				vk_Next: begin
+					SavScrCol := ScrCol;
+					Cell := CharIdxToCell (CursorPos);
+					Inc (Cell.Row, PageHeight - 1);
+					Cell.Col := ScrColToCol (Cell.Row);
+					NewPos := CellToCharIdx (Cell);
+				end;
+				vk_Home: begin
+					Cell := CharIdxToCell (CursorPos);
+					if ssCtrl in Shift then
+						Cell.Row := 1;
+					Cell.Col := 1;
+					NewPos := CellToCharIdx (Cell);
+				end;
+				vk_End: begin
+					Cell := CharIdxToCell (CursorPos);
+					if ssCtrl in Shift then
+						Cell.Row := LineCount;
+					Cell.Col := LineLength [Cell.Row] + 1;
+					NewPos := CellToCharIdx (Cell);
+				end;
+				vk_Escape:
+					if FDragging and Assigned (DragOrigRange) then begin
+						DragOrigRange.Text := Selection.Text;
+						Selection.Text := '';
+						Selection.Assign (DragOrigRange);
+						CancelDragging;
+						DontNotify := False;
+					end;
+			end;
+			if NewPos <> Low (Integer) then begin
+				if ssShift in Shift then
+					CursorPos := NewPos
+				else
+					NoSelAtPos (NewPos);
+				ScrCol := SavScrCol;
+				ScrollInView (0);
+			end;
+		end;
+		if (UpCase (Char (Key)) = 'Z') and (ssCtrl in Shift) then begin
+			if ssShift in Shift then
+				Redo
+			else
+				Undo;
+		end;
+		if FDragging and (Key = vk_Control) then begin
+			P := ScreenToClient (Mouse.CursorPos);
+			MouseMove (Shift, P.X, P.Y);
+		end;
+	end;
+	if Shift = [ssCtrl] then
+		case UpCase (Char (Key)) of
+			'X': if not ReadOnly then CutToClipboard;
+			'C': CopyToClipboard;
+			'V': if not ReadOnly then PasteFromClipboard;
+		end;
+end;
+
+procedure TMemoComponent.HandleKeyPress(var Key: Char);
+var
+	BeginLn,
+	FirstChr: Integer;
+begin
+	if ((Key >= #32) and (Key <> #127)) or (Key = #13) then
+		if not ReadOnly then
+			with Selection do begin
+				if Key = #13 then begin
+					if AutoIndent then begin
+						BeginLn := CellToCharIdx (TextCell (StartRowCol.Row, 1));
+						FirstChr := FirstNonWhiteSpace (Copy (Self.Text, BeginLn, RStart - BeginLn));
+						Text := #13#10 + Copy (Self.Text, BeginLn, FirstChr - 1);
+					end else
+						Text := #13#10;
+				end else
+					Text := Key;
+				ScrollInView (4);
+			end;
+end;
+
+procedure TMemoComponent.HandleKeyUp(var Key: Word; Shift: TShiftState);
+var
+	P: TPoint;
+begin
+	if (not ReadOnly) and FDragging and (Key = vk_Control) then begin
+		P := ScreenToClient (Mouse.CursorPos);
+		MouseMove (Shift, P.X, P.Y);
+	end;
+end;
+
+function TMemoComponent.IsUndoBeginEndBlock(Op: PUndoOperation): Boolean;
+begin
+	Result := Op.RStart = -1;
+end;
+
+procedure TMemoComponent.KeyPress(var Key: Char);
+begin
+	inherited;
+	HandleKeyPress (Key);
+end;
+
+procedure TMemoComponent.MakeRedoOperation(Op: PUndoOperation);
+begin
+	if Assigned (Op) then begin
+		Op.NextItem := FRedoStack;
+		FRedoStack := Op;
+	end;
+end;
+
+procedure TMemoComponent.MakeUndoOperation(Op: PUndoOperation);
+begin
+	if Assigned (Op) then begin
+		Op.NextItem := FUndoStack;
+		FUndoStack := Op;
+	end;
+end;
+
+procedure TMemoComponent.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+var
+	Cell: TTextCell;
+	NewPos: Integer;
+begin
+	inherited;
+	if not FDblClicked then begin
+		try
+			SetFocus;
+		except end;
+		if (Button = mbLeft) or ((Button = mbRight) and (Selection.RLength <= 0)) then begin
+			Cell := ScrPointToScrCell (Point (X, Y));
+			Inc (Cell.Row, VisibleRange.TopRow - 1);
+			Inc (Cell.Col, VisibleRange.LeftCol - 1);
+			CellFromScrCol (Cell);
+			NewPos := CellToCharIdx (Cell);
+			with Selection do
+				if ssShift in Shift then
+					CursorPos := NewPos
+				else begin
+					if DragDropEditing and (RLength > 0) and (RStart <= NewPos) and (REnd >= NewPos - 1) and (not ReadOnly) then
+						FStartDrag := True
+					else
+						NoSelAtPos (NewPos)
+				end;
+			if not (FSelecting or FStartDrag) then begin
+				FSelecting := True;
+				if HandleAllocated then
+					SetTimer (Handle, 1, 50, nil);
+			end;
+		end;
+	end;
+end;
+
+procedure TMemoComponent.MouseMove(Shift: TShiftState; X, Y: Integer);
+begin
+	inherited;
+	if FStartDrag and (not FDragging) then begin
+		if not Assigned (DragOrigRange) then
+			DragOrigRange := TMCRange.Create (TrackedRanges);
+		with DragOrigRange do begin
+			RStart := Selection.RStart;
+			RLength := 0;
+		end;
+		FDragging := True;
+		SetCurCursor (ccDrag, True);
+		if HandleAllocated and (not FSelecting) then
+			SetTimer (Handle, 1, 50, nil);
+		FSelecting := False;
+		DontNotify := True;
+	end;
+	FStartDrag := False;
+	if FDragging and Assigned (DragOrigRange) then begin
+		if ssCtrl in Shift then
+			DragOrigRange.Text := Selection.Text
+		else
+			DragOrigRange.Text := '';
+	end;
+	MouseMoveInternal (X, Y);
+end;
+
+procedure TMemoComponent.MouseMoveInternal(X, Y: Integer);
+var
+	Cell: TTextCell;
+	NewPos: Integer;
+	SelText,
+	MoveText: string;
+	DRStart,
+	DREnd: Integer;
+begin
+	if (FSelecting or FDragging) and (not FDblClicked) then begin
+		Cell := ScrPointToScrCell (Point (X, Y));
+		Inc (Cell.Row, VisibleRange.TopRow - 1);
+		Inc (Cell.Col, VisibleRange.LeftCol - 1);
+		CellFromScrCol (Cell);
+		NewPos := CellToCharIdx (Cell);
+		if FSelecting then
+			Selection.CursorPos := NewPos
+		else if FDragging then begin
+			if Assigned (DragOrigRange) then begin
+				DRStart := DragOrigRange.RStart;
+				DREnd := DragOrigRange.REnd;
+			end else begin
+				DRStart := 0;
+				DREnd := 0;
+			end;
+			if (NewPos <= DRStart) or (NewPos > DREnd) then begin
+				with Selection do begin
+					SelText := Text;
+					if NewPos < RStart then begin
+						if (RStart - NewPos >= Length (SelText)) or ((DRStart >= NewPos) and (DRStart <= RStart)) then begin
+							Text := '';
+							NoSelAtPos (NewPos);
+							Text := SelText;
+							RStart := NewPos;
+							RLength := Length (SelText);
+						end else
+							with TMCRange.Create (nil) do try
+								Editor := Self;
+								RStart := NewPos;
+								RLength := Selection.RStart - NewPos;
+								MoveText := Text;
+								Text := '';
+								RStart := Selection.REnd + 1;
+								RLength := 0;
+								Text := MoveText;
+								if Assigned (DragOrigRange) then
+									with DragOrigRange do
+										if (REnd < RStart) and (RStart = Selection.REnd + 1) then
+											RStart := RStart + Length (MoveText);
+							finally
+								Free;
+							end;
+					end else if NewPos > REnd + 1 then begin
+						if (NewPos - (REnd + 1) >= Length (SelText)) or ((DRStart >= REnd + 1) and (DRStart <= NewPos)) then begin
+							Text := '';
+							NoSelAtPos (NewPos - Length (SelText));
+							Text := SelText;
+							RStart := NewPos - Length (SelText);
+							RLength := Length (SelText);
+						end else
+							with TMCRange.Create (nil) do try
+								Editor := Self;
+								RStart := Selection.REnd + 1;
+								RLength := NewPos - (Selection.REnd + 1);
+								MoveText := Text;
+								Text := '';
+								RStart := Selection.RStart;
+								RLength := 0;
+								Text := MoveText;
+							finally
+								Free;
+							end;
+					end;
+				end;
+			end;
+		end;
+	end;
+	if DragDropEditing and (not FStartDrag) and (not FDragging) and (not ReadOnly) then begin
+		Cell := ScrPointToScrCell (Point (X, Y));
+		Inc (Cell.Row, VisibleRange.TopRow - 1);
+		Inc (Cell.Col, VisibleRange.LeftCol - 1);
+		CellFromScrCol (Cell);
+		NewPos := CellToCharIdx (Cell);
+		with Selection do begin
+			if (RLength > 0) and (RStart <= NewPos) and (REnd >= NewPos - 1) then
+				SetCurCursor (ccArrow)
+			else
+				SetCurCursor (ccIBeam);
+		end;
+	end;
+end;
+
+procedure TMemoComponent.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+var
+	Cell: TTextCell;
+	NewPos: Integer;
+	Op: PUndoOperation;
+begin
+	inherited;
+	if FStartDrag then begin
+		FStartDrag := False;
+		Cell := ScrPointToScrCell (Point (X, Y));
+		Inc (Cell.Row, VisibleRange.TopRow - 1);
+		Inc (Cell.Col, VisibleRange.LeftCol - 1);
+		CellFromScrCol (Cell);
+		NewPos := CellToCharIdx (Cell);
+		Selection.NoSelAtPos (NewPos);
+	end;
+	if (Button in [mbLeft, mbRight]) and (FSelecting or FDragging) and (not FDblClicked) then begin
+		if FDragging then begin
+			if Assigned (DragOrigRange) then begin
+				if ssCtrl in Shift then
+					DragOrigRange.Text := Selection.Text
+				else
+					DragOrigRange.Text := '';
+			end;
+			if AllowUndo and ((Selection.RStart <> DragOrigRange.RStart) or (DragOrigRange.RLength > 0)) then begin
+				ClearRedo;
+				MakeUndoOperation (CreateUndoBeginEndBlock);
+				if Assigned (DragOrigRange) and (DragOrigRange.RLength <= 0) then begin
+					New (Op);
+					Op.RStart := DragOrigRange.RStart;
+					if Op.RStart > Selection.RStart then
+						Dec (Op.RStart, Selection.RLength);
+					Op.REnd := Op.RStart - 1;
+					Op.NewText := Selection.Text;
+					MakeUndoOperation (Op);
+				end;
+				New (Op);
+				Op.RStart := Selection.RStart;
+				Op.REnd := Selection.REnd;
+				Op.NewText := '';
+				MakeUndoOperation (Op);
+				MakeUndoOperation (CreateUndoBeginEndBlock);
+				DontNotify := False;
+				Change;
+				SelectionChange;
+			end;
+			DontNotify := False;
+		end;
+		CancelDragging;
+	end;
+	FDblClicked := False;
+	if Assigned (DragOrigRange) then begin
+		DragOrigRange.Free;
+		DragOrigRange := nil;
+	end;
+end;
+
+procedure TMemoComponent.Paint;
+begin
+	inherited;
+	if not DrawingSuspended then begin
+		Selection.HideCaret;
+		if Bitmapped then begin
+			UpdateDrawBmp;
+			Canvas.Draw (0, 0, DrawBmp)
+		end else begin
+			DrawBorder (Rect (0, 0, LeftMargin, ClientHeight), Rect (0, 0, ClientWidth, TopMargin), Canvas);
+			VisibleRange.DrawRange;
+		end;
+		Selection.ShowCaret;
+	end;
+end;
+
+procedure TMemoComponent.PasteFromClipboard;
+begin
+	Perform (wm_Paste, 0, 0);
+end;
+
+procedure TMemoComponent.ReCreateCaret;
+begin
+	if HasFocus and HandleAllocated then begin
+		FreeCaret;
+		CreateCaret (Handle, 0, 2, FontHeight - 2);
+		FCaretCreated := True;
+		with Selection do begin
+			UpdateCaretPos;
+			ShowCaret;
+		end;
+	end;
+end;
+
+procedure TMemoComponent.Redo;
+begin
+	Perform (em_Undo, 1, 0);
+end;
+
+procedure TMemoComponent.RemoveTrSp;
+var
+	I: Integer;
+begin
+	DontNotify := True;
+	try
+		Selection.DoChanging;
+		try
+			for I := 1 to LineCount do
+				RemoveTrSpFromLine (I);
+		finally
+			Selection.DoChange;
+		end;
+	finally
+		DontNotify := False;
+	end;
+	Self.Change;
+end;
+
+procedure TMemoComponent.RemoveTrSpFromLine(LineIdx: Integer);
+var
+	I,
+	LastChar: Integer;
+	S: string;
+begin
+	with TMCRange.Create (nil) do try
+		Editor := Self;
+		StartRowCol := TextCell (LineIdx, 1);
+		EndRowCol := TextCell (LineIdx + 1, -2);
+		S := Text;
+		LastChar := 0;
+		for I := Length (S) downto 1 do
+			if not (S [I] in [' ', #9]) then begin
+				LastChar := I;
+				Break;
+			end;
+		if LastChar < Length (S) then begin
+			RStart := RStart + LastChar;
+			Clear;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMemoComponent.RemoveTrSpFromString(var Str: string; IncludeLastLine: Boolean);
+var
+	I,
+	P,
+	NextChar,
+	CurLineStart: Integer;
+begin
+	CurLineStart := 1;
+	repeat
+		NextChar := Length (Str) + 1;
+		for I := CurLineStart to Length (Str) + 1 do begin
+			if ((I <= Length (Str)) and (Str [I] = #13)) or (IncludeLastLine and (I > Length (Str))) then begin
+				NextChar := I + 1;
+				for P := I - 1 downto CurLineStart do begin
+					if Str [P] in [' ', #9] then
+						Delete (Str, P, 1)
+					else
+						Break;
+				end;
+				Break;
+			end;
+		end;
+		while (NextChar <= Length (Str)) and (Str [NextChar] in [#13, #10]) do
+			Inc (NextChar);
+		CurLineStart := NextChar;
+	until NextChar > Length (Str);
+end;
+
+procedure TMemoComponent.ReplaceText(Range: TCustomRange; const NewText: string);
+var
+	RS,
+	I,
+	L,
+	LI,
+	EI,
+	LC,
+	P,
+	BC,
+	LnCh,
+	RangeStart,
+	RangeEnd,
+	IStart,
+	IEnd: Integer;
+	S: string;
+	BlUndo,
+	PUN,
+	ChangedTopRow: Boolean;
+	Op: PUndoOperation;
+begin
+	PUN := False;
+	LnCh := 0;
+	RangeStart := Range.RStart;
+	RangeEnd := Range.REnd;
+	with Selection do begin
+		DoChanging;
+		FOldSel.Free;
+		FOldSel := nil;
+	end;
+	RS := RangeStart;
+	S := AdjustLineBreaks (NewText);
+	if RemoveTrailingSpaces then
+		RemoveTrSpFromString (S);
+	L := Length (S);
+	if AllowUndo and not (FInUndo or FDragging) then begin
+		ClearRedo;
+		BlUndo := False;
+		Op := FUndoStack;
+		if Assigned (Op) then begin
+			if Range.RLength <= 0 then begin
+				if (L > 0) and (Length (Op.NewText) <= 0) and (Op.REnd >= Op.RStart) then begin
+					if Op.REnd + 1 = RS then begin
+						Inc (Op.REnd, L);
+						BlUndo := True;
+					end;
+				end;
+			end else begin
+				if (L <= 0) and (Length (Op.NewText) > 0) and (Op.REnd < Op.RStart) then begin
+					if Op.RStart = RS then begin
+						Op.NewText := Op.NewText + Range.Text;
+						BlUndo := True;
+					end else if Op.RStart = Range.REnd + 1 then begin
+						Dec (Op.RStart, Range.RLength);
+						Dec (Op.REnd, Range.RLength);
+						Op.NewText := Range.Text + Op.NewText;
+						BlUndo := True;
+					end;
+				end;
+			end;
+		end;
+		if not BlUndo then begin
+			New (Op);
+			Op.RStart := RS;
+			Op.REnd := RS + L - 1;
+			Op.NewText := Range.Text;
+			MakeUndoOperation (Op);
+		end;
+	end;
+	LI := CharIdxToCell(Range.RStart).Row;
+	EI := CharIdxToCell(Range.REnd+1).Row;
+	LC := L - Range.RLength;
+	if VisualLineLength [EI] >= FLongestLineLength then begin
+		FLongestLineLength := 0;
+		PUN := True;
+	end;
+	with FLineStarts do
+		if (Range.RStart = 1) and (Range.REnd = TextLength) then begin
+			LnCh := Count - 1;
+			Clear;
+			Add (1);
+			FLongestLineLength := 0;
+			PUN := True;
+		end else
+			for I := EI - 1 downto LI do begin
+				if (not PUN) and (VisualLineLength [I + 1] >= FLongestLineLength) then begin
+					FLongestLineLength := 0;
+					PUN := True;
+				end;
+				Delete (I);
+				Dec (LnCh);
+			end;
+	Delete (FText, RS, Range.RLength);
+	Insert (S, FText, RS);
+	FTextLength := Length (FText);
+	BC := 0;
+	for P := 1 to Length (S) - 1 do
+		if S [P] = #13 then begin
+			FLineStarts.Insert (LI + BC, Range.RStart + P + 1);
+			Inc (LnCh);
+			Inc (BC);
+		end;
+	with FLineStarts do begin
+		for I := LI + BC to Count - 1 do
+			Items [I] := Items [I] + LC;
+		if FLongestLineLength <= 0 then begin
+			IStart := 0;
+			IEnd := Count - 1;
+		end else begin
+			IStart := LI - 1;
+			IEnd := LI + BC;
+		end;
+		for I := IStart to IEnd do
+			if (I >= 0) and (I < Count) then begin
+				P := VisualLineLength [I + 1];
+				if P > FLongestLineLength then begin
+					FLongestLineLength := P;
+					PUN := True;
+				end;
+			end;
+	end;
+	with TrackedRanges do
+		for I := Count - 1 downto 0 do
+			if (Items [I] <> Range) and (Items [I] <> VisibleRange) then
+				Items[I].InternalDoMove (RangeStart, RangeEnd, LC);
+	if Assigned (FOnReplaceText) then
+		FOnReplaceText (Self, RS, LC);
+	ChangedTopRow := False;
+	if LnCh <> 0 then
+		with VisibleRange do
+			if LI < FTopRow then begin
+				Inc (FTopRow, LnCh);
+				ChangedTopRow := True;
+			end;
+	if Range is TSelectionRange then begin
+		TSelectionRange(Range).NoSelAtPos (RS + L);
+	end else
+		Range.RLength := L;
+	TextChangeNotification (RS, L - LC, L);
+	if PUN or (LnCh <> 0) then
+		UpdatePageSize;
+	with TMCRange.Create (nil) do begin
+		Editor := Self;
+		if ChangedTopRow then
+			RStart := VisibleRange.RStart
+		else
+			RStart := RS;
+		if LnCh <> 0 then
+			EndRowCol := VisibleRange.EndRowCol
+		else
+			EndRowCol := TextCell (EI + 1, 0);
+		DrawRange;
+		Free;
+	end;
+	TextChangeNotificationAfter;
+	Selection.DoChange;
+	Change;
+end;
+
+function TMemoComponent.ScrCellToScrPoint(Cell: TTextCell): TPoint;
+begin
+	with Cell do
+		Result := Point ((Col - 1) * FontWidth + LeftMargin, (Row - 1) * FontHeight + TopMargin);
+end;
+
+procedure TMemoComponent.ScrollCaret;
+begin
+	Selection.ScrollInView (4);
+end;
+
+function TMemoComponent.ScrPointToScrCell(P: TPoint): TTextCell;
+begin
+	with P do
+		Result := TextCell ((Y - TopMargin) div FontHeight + 1, (X - LeftMargin + FontWidth div 2) div FontWidth + 1);
+end;
+
+procedure TMemoComponent.SelectAll;
+begin
+	Selection.Assign (WholeText);
+end;
+
+procedure TMemoComponent.SelectionChange;
+begin
+	if not DontNotify then begin
+		if Assigned (FOnSelectionChange) then
+			FOnSelectionChange(Self);
+	end;
+end;
+
+procedure TMemoComponent.SetAllowUndo(const Value: Boolean);
+begin
+	FAllowUndo := Value;
+	if not FAllowUndo then
+		ClearUndo;
+end;
+
+procedure TMemoComponent.SetAlwaysShowCaret(const Value: Boolean);
+begin
+	if FAlwaysShowCaret <> Value then begin
+		FAlwaysShowCaret := Value;
+		Selection.ShowCaret;
+	end;
+end;
+
+procedure TMemoComponent.SetBitmapped(const Value: Boolean);
+begin
+	FBitmapped := Value;
+	if (not Value) and Assigned (DrawBmp) then begin
+		DrawBmp.Free;
+		DrawBmp := nil;
+	end;
+end;
+
+procedure TMemoComponent.SetBorderStyle(const Value: TBorderStyle);
+begin
+	if FBorderStyle <> Value then begin
+		FBorderStyle := Value;
+		RecreateWnd;
+	end;
+end;
+
+procedure TMemoComponent.SetCurCursor(NewCursor: TCurCursor; Temporary: Boolean);
+var
+	CursorHandle: ^HCursor;
+begin
+	if FCurCursor <> NewCursor then begin
+		if FTempCursor and (NewCursor = ccNone) then
+			NewCursor := FCurCursor;
+		case NewCursor of
+			ccIBeam: begin
+				CursorHandle := @FCursorIBeam;
+				if CursorHandle^ = 0 then
+					CursorHandle^ := LoadCursor (0, idc_IBeam);
+			end;
+			ccArrow: begin
+				CursorHandle := @FCursorArrow;
+				if CursorHandle^ = 0 then
+					CursorHandle^ := LoadCursor (0, idc_Arrow);
+			end;
+			ccDrag: begin
+				CursorHandle := @FCursorDrag;
+				if CursorHandle^ = 0 then
+					CursorHandle^ := Screen.Cursors [crDrag];
+			end;
+			else
+				CursorHandle := nil;
+		end;
+		if Assigned (CursorHandle) and (CursorHandle^ <> 0) and not (csDesigning in ComponentState) then begin
+			if Temporary then begin
+				SetCursor (CursorHandle^);
+				FTempCursor := True;
+			end else begin
+				if FTempCursor then begin
+					SetCursor (CursorHandle^);
+					FTempCursor := False;
+				end;
+				SetClassLong (Handle, gcl_HCursor, CursorHandle^);
+				FCurCursor := NewCursor;
+			end;
+		end;
+	end;
+end;
+
+procedure TMemoComponent.SetHasFocus(const Value: Boolean);
+begin
+	if FHasFocus <> Value then begin
+		FHasFocus := Value;
+		if not HasFocus then
+			FreeCaret;
+		Selection.DrawRange;
+		if HasFocus then
+			ReCreateCaret;
+	end;
+end;
+
+procedure TMemoComponent.SetLeftMargin(const Value: Integer);
+begin
+	if FLeftMargin <> Value then begin
+		FLeftMargin := Value;
+		UpdatePageSize;
+		VisibleRange.Update;
+		VisibleRange.DrawRange;
+		Selection.UpdateCaretPos;
+	end;
+end;
+
+procedure TMemoComponent.SetLines(const Value: TStrings);
+begin
+	FLines.Assign (Value);
+end;
+
+procedure TMemoComponent.SetReadOnly(const Value: Boolean);
+begin
+	if FReadOnly <> Value then begin
+		FReadOnly := Value;
+		Selection.ShowCaret;
+	end;
+end;
+
+procedure TMemoComponent.SetRemoveTrailingSpaces(const Value: Boolean);
+begin
+	if FRemoveTrailingSpaces <> Value then begin
+		FRemoveTrailingSpaces := Value;
+		if Value then
+			RemoveTrSp;
+	end;
+end;
+
+procedure TMemoComponent.SetScrollBars(const Value: TScrollStyle);
+begin
+	if FScrollBars <> Value then begin
+		FScrollBars := Value;
+		RecreateWnd;
+	end;
+end;
+
+procedure TMemoComponent.SetSelLength(const Value: Integer);
+begin
+	Selection.RLength := Value;
+end;
+
+procedure TMemoComponent.SetSelStart(const Value: Integer);
+begin
+	Selection.NoSelAtPos (Value + 1);
+end;
+
+procedure TMemoComponent.SetTabSize(const Value: Integer);
+var
+	I: Integer;
+begin
+	if FTabSize <> Value then begin
+		FTabSize := Value;
+		if FTabSize < 1 then
+			FTabSize := 1;
+		Selection.DoChanging;
+		FLongestLineLength := 0;
+		for I := 0 to LineCount do
+			if FLongestLineLength < VisualLineLength [I] then
+				FLongestLineLength := VisualLineLength [I];
+		UpdatePageSize;
+		VisibleRange.Update;
+		VisibleRange.DrawRange;
+		Selection.UpdateCaretPos;
+		Selection.DoChange;
+	end;
+end;
+
+procedure TMemoComponent.SetText(const Value: TCaption);
+begin
+	WholeText.Text := Value;
+end;
+
+procedure TMemoComponent.SetTopMargin(const Value: Integer);
+begin
+	if FTopMargin <> Value then begin
+		FTopMargin := Value;
+		UpdatePageSize;
+		VisibleRange.Update;
+		VisibleRange.DrawRange;
+		Selection.UpdateCaretPos;
+	end;
+end;
+
+function TMemoComponent.TabSpacesAtPos(P: Integer): Integer;
+var
+	I: Integer;
+	RS: TTextCell;
+	Ps: Integer;
+begin
+	if TabSize <= 1 then
+		Result := TabSize
+	else begin
+		RS := CharIdxToCell (P);
+		RS.Col := 1;
+		Ps := 0;
+		for I := CellToCharIdx (RS) to P - 1 do begin
+			if Text [I] = #9 then
+				Ps := (Ps div TabSize + 1) * TabSize
+			else
+				Inc (Ps);
+		end;
+		Result := TabSize - Ps mod TabSize;
+	end;
+end;
+
+procedure TMemoComponent.TextChangeNotification(StartPos, OldLength,
+  NewLength: Integer);
+begin
+end;
+
+procedure TMemoComponent.TextChangeNotificationAfter;
+begin
+end;
+
+procedure TMemoComponent.Undo;
+begin
+	Perform (em_Undo, 0, 0);
+end;
+
+procedure TMemoComponent.UpdateDrawBmp;
+begin
+	if Bitmapped then begin
+		if not Assigned (DrawBmp) then
+			DrawBmp := TBitmap.Create;
+		if (DrawBmp.Width <> ClientWidth) or (DrawBmp.Height <> ClientHeight) then begin
+			DrawBmp.Width := ClientWidth;
+			DrawBmp.Height := ClientHeight;
+			DrawBorder (Rect (0, 0, LeftMargin, ClientHeight), Rect (0, 0, ClientWidth, TopMargin), DrawBmp.Canvas);
+		end;
+	end else
+		if Assigned (DrawBmp) then begin
+			DrawBmp.Free;
+			DrawBmp := nil;
+		end;
+end;
+
+procedure TMemoComponent.UpdateFontSize;
+const
+	WidthMeasureChar = 'M';
+	HeightMeasureChar = 'Q';
+procedure TryStyle(Style: TFontStyle);
+begin
+	Canvas.Font.Style := Canvas.Font.Style + [Style];
+	if FontWidth <> Canvas.TextWidth (WidthMeasureChar) then
+		Include (FForbiddenFontStyles, Style);
+	Canvas.Font.Assign (Font);
+end;
+begin
+	FForbiddenFontStyles := [];
+	if HandleAllocated and Assigned (Parent) then begin
+		Canvas.Font.Assign (Font);
+		FontWidth := Canvas.TextWidth (WidthMeasureChar);
+		FontHeight := Canvas.TextHeight (HeightMeasureChar);
+		TryStyle (fsBold);
+		TryStyle (fsItalic);
+		ReCreateCaret;
+		UpdatePageSize;
+	end;
+end;
+
+procedure TMemoComponent.UpdatePageSize;
+var
+	ScrollInfo: TScrollInfo;
+	DrawAll: Boolean;
+begin
+	if HandleAllocated and Assigned (Parent) then begin
+		VisibleRange.DoChanging;
+		DrawAll := Bitmapped and ((not Assigned (DrawBmp)) or (DrawBmp.Width < ClientWidth) or (DrawBmp.Height < ClientHeight));
+		UpdateDrawBmp;
+		if FontHeight <= 0 then
+			FontHeight := 13;
+		if FontWidth <= 0 then
+			FontWidth := 8;
+		if HandleAllocated and Assigned (Parent) then begin
+			PageHeight := (ClientHeight - TopMargin) div FontHeight;
+			PageWidth := (ClientWidth - LeftMargin) div FontWidth;
+		end else begin
+			PageHeight := 1;
+			PageWidth := 1;
+		end;
+		if PageHeight < 1 then
+			PageHeight := 1;
+		if PageWidth < 1 then
+			PageWidth := 1;
+		VisibleRange.Update;
+		if HandleAllocated then begin
+			with ScrollInfo do begin
+				cbSize := SizeOf (ScrollInfo);
+				fMask := sif_All or sif_DisableNoScroll;
+				nMin := 1;
+				nMax := LineCount;
+				nPos := VisibleRange.TopRow;
+				nPage := PageHeight;
+			end;
+			SetScrollInfo (Handle, sb_Vert, ScrollInfo, True);
+			with ScrollInfo do begin
+				nMin := 1;
+				nMax := LongestLineLength;
+				nPos := VisibleRange.LeftCol;
+				nPage := PageWidth;
+			end;
+			SetScrollInfo (Handle, sb_Horz, ScrollInfo, True);
+		end;
+		VisibleRange.DoChange;
+		if DrawAll then
+			VisibleRange.DrawRange;
+	end;
+end;
+
+procedure TMemoComponent.WMClear(var Message: TWMClear);
+begin
+	inherited;
+	Selection.Clear;
+end;
+
+procedure TMemoComponent.WMCopy(var Message: TWMCopy);
+begin
+	inherited;
+	if Selection.RLength > 0 then
+		Clipboard.AsText := Selection.Text;
+end;
+
+procedure TMemoComponent.WMCut(var Message: TWMCut);
+begin
+	inherited;
+	if Selection.RLength > 0 then begin
+		Clipboard.AsText := Selection.Text;
+		Selection.Clear;
+	end;
+end;
+
+procedure TMemoComponent.WMEraseBkgnd(var Message: TWMEraseBkgnd);
+begin
+	Message.Result := 1;
+end;
+
+procedure TMemoComponent.WMGetDlgCode(var Message: TWMGetDlgCode);
+begin
+	inherited;
+	if ReadOnly then
+		Message.Result := Message.Result or dlgc_WantArrows
+	else
+		Message.Result := Message.Result or dlgc_WantAllKeys;
+end;
+
+procedure TMemoComponent.WMGetText(var Message: TWMGetText);
+begin
+	StrPLCopy (Message.Text, Text, Message.TextMax);
+	Message.Result := StrLen (Message.Text);
+end;
+
+procedure TMemoComponent.WMGetTextLength(var Message: TWMGetTextLength);
+begin
+	Message.Result := TextLength;
+end;
+
+procedure TMemoComponent.WMHScroll(var Message: TWMHScroll);
+var
+	ScrollPos: Integer;
+	OldPos: Integer;
+begin
+	VisibleRange.DoChanging;
+	inherited;
+	OldPos := VisibleRange.LeftCol;
+	ScrollPos := OldPos;
+	with Message do begin
+		if ScrollCode in [sb_ThumbTrack, sb_ThumbPosition] then
+			ScrollPos := Pos
+		else begin
+			case ScrollCode of
+				sb_Top: ScrollPos := 1;
+				sb_Bottom: ScrollPos := LongestLineLength - PageWidth + 1;
+				sb_LineLeft: ScrollPos := OldPos - 1;
+				sb_LineRight: ScrollPos := OldPos + 1;
+				sb_PageLeft: ScrollPos := OldPos - PageWidth;
+				sb_PageRight: ScrollPos := OldPos + PageWidth;
+			end;
+		end;
+		Result := 0;
+	end;
+	if ScrollPos > LongestLineLength - PageWidth + 1 then
+		ScrollPos := LongestLineLength - PageWidth + 1;
+	if ScrollPos < 1 then
+		ScrollPos := 1;
+	if ScrollPos <> OldPos then begin
+		SetScrollPos (Handle, sb_Horz, ScrollPos, True);
+		VisibleRange.FLeftCol := ScrollPos;
+		VisibleRange.DoChange;
+		Update;
+	end else
+		VisibleRange.DoDiscardChanges;
+end;
+
+procedure TMemoComponent.WMKeyDown(var Message: TWMKeyDown);
+begin
+	inherited;
+	HandleKeyDown (Message.CharCode, KeyDataToShiftState (Message.KeyData));
+end;
+
+procedure TMemoComponent.WMKeyUp(var Message: TWMKeyUp);
+begin
+	HandleKeyUp (Message.CharCode, KeyDataToShiftState (Message.KeyData));
+	inherited;
+end;
+
+procedure TMemoComponent.WMKillFocus(var Message: TWMKillFocus);
+begin
+	inherited;
+	HasFocus := False;
+end;
+
+procedure TMemoComponent.WMPaste(var Message: TWMPaste);
+begin
+	inherited;
+	Selection.Text := Clipboard.AsText;
+	Selection.ScrollInView (1);
+end;
+
+procedure TMemoComponent.WMSetFocus(var Message: TWMSetFocus);
+begin
+	inherited;
+	HasFocus := True;
+end;
+
+procedure TMemoComponent.WMSetText(var Message: TWMSetText);
+begin
+	Text := StrPas (Message.Text);
+	Message.Result := 1;
+end;
+
+procedure TMemoComponent.WMSize(var Message: TWMSize);
+begin
+	inherited;
+	UpdatePageSize;
+end;
+
+procedure TMemoComponent.WMTimer(var Message: TWMTimer);
+var
+	P: TPoint;
+	DLeft,
+	DTop: Integer;
+begin
+	inherited;
+	if (Message.TimerID = 1) and (FSelecting or FDragging) then begin
+		P := ScreenToClient (Mouse.CursorPos);
+		DLeft := 0;
+		DTop := 0;
+		if P.X < 0 then
+			DLeft := -((-1 - P.X) div ScrollOffset + 1)
+		else if P.X >= ClientWidth then
+			DLeft := ((P.X - ClientWidth) div ScrollOffset + 1);
+		if P.Y < 0 then
+			DTop := -((-1 - P.Y) div ScrollOffset + 1)
+		else if P.Y >= ClientHeight then
+			DTop := ((P.Y - ClientHeight) div ScrollOffset + 1);
+		if (DLeft <> 0) or (DTop <> 0) then begin
+			with VisibleRange do begin
+				if DLeft <> 0 then
+					LeftCol := LeftCol + DLeft;
+				if DTop <> 0 then
+					TopRow := TopRow + DTop;
+			end;
+			MouseMoveInternal (P.X, P.Y);
+		end;
+	end;
+end;
+
+procedure TMemoComponent.WMVScroll(var Message: TWMVScroll);
+var
+	ScrollPos: Integer;
+	OldPos: Integer;
+begin
+	VisibleRange.DoChanging;
+	inherited;
+	OldPos := GetScrollPos (Handle, sb_Vert);
+	ScrollPos := OldPos;
+	with Message do begin
+		if ScrollCode in [sb_ThumbTrack, sb_ThumbPosition] then
+			ScrollPos := Pos
+		else begin
+			case ScrollCode of
+				sb_Top: ScrollPos := 1;
+				sb_Bottom: ScrollPos := LineCount - PageHeight + 1;
+				sb_LineUp: ScrollPos := OldPos - 1;
+				sb_LineDown: ScrollPos := OldPos + 1;
+				sb_PageUp: ScrollPos := OldPos - PageHeight;
+				sb_PageDown: ScrollPos := OldPos + PageHeight;
+			end;
+		end;
+		Result := 0;
+	end;
+	if ScrollPos > LineCount - PageHeight + 1 then
+		ScrollPos := LineCount - PageHeight + 1;
+	if ScrollPos < 1 then
+		ScrollPos := 1;
+	if ScrollPos <> OldPos then begin
+		SetScrollPos (Handle, sb_Vert, ScrollPos, True);
+		VisibleRange.FTopRow := ScrollPos;
+		VisibleRange.DoChange;
+		Update;
+	end else
+		VisibleRange.DoDiscardChanges;
+end;
+
+{ TIntegerList }
+
+function TIntegerList.Add(Item: Integer): Integer;
+begin
+	Result := FList.Add (Pointer (Item));
+end;
+
+procedure TIntegerList.Clear;
+begin
+	FList.Clear;
+end;
+
+constructor TIntegerList.Create;
+begin
+	inherited;
+	FList := TList.Create;
+end;
+
+procedure TIntegerList.Delete(Index: Integer);
+begin
+	FList.Delete (Index);
+end;
+
+destructor TIntegerList.Destroy;
+begin
+	FList.Free;
+	inherited;
+end;
+
+function TIntegerList.GetCount: Integer;
+begin
+	Result := FList.Count;
+end;
+
+function TIntegerList.GetItem(ItemIndex: Integer): Integer;
+begin
+	Result := Integer (FList.Items [ItemIndex]);
+end;
+
+procedure TIntegerList.Insert(Index, Item: Integer);
+begin
+	FList.Insert (Index, Pointer (Item));
+end;
+
+procedure TIntegerList.SetCount(const Value: Integer);
+begin
+	FList.Count := Value;
+end;
+
+procedure TIntegerList.SetItem(ItemIndex: Integer; const Value: Integer);
+begin
+	FList.Items [ItemIndex] := Pointer (Value);
+end;
+
+{ TMemoComponentStrings }
+
+procedure TMemoComponentStrings.Clear;
+begin
+	Memo.Clear;
+end;
+
+procedure TMemoComponentStrings.Delete(LineIndex: Integer);
+var
+	Range: TCustomRange;
+begin
+	Range := TMCRange.Create (nil);
+	with Range do begin
+		Editor := Memo;
+		if LineIndex < Memo.LineCount - 1 then begin
+			StartRowCol := TextCell (LineIndex + 1, 1);
+			EndRowCol := TextCell (LineIndex + 2, 0);
+		end else begin
+			StartRowCol := TextCell (LineIndex + 1, -1);
+			EndRowCol := TextCell (LineIndex + 2, -2);
+		end;
+		Clear;
+		Free;
+	end;
+end;
+
+function TMemoComponentStrings.Get(LineIndex: Integer): string;
+var
+	Range: TCustomRange;
+begin
+	Range := TMCRange.Create (nil);
+	with Range do begin
+		Editor := Memo;
+		StartRowCol := TextCell (LineIndex + 1, 1);
+		EndRowCol := TextCell (LineIndex + 2, -2);
+		Result := Text;
+		Free;
+	end;
+end;
+
+function TMemoComponentStrings.GetCount: Integer;
+begin
+	if Memo.TextLength > 0 then
+		Result := Memo.LineCount
+	else
+		Result := 0;
+end;
+
+function TMemoComponentStrings.GetTextStr: string;
+begin
+	Result := Memo.Text;
+end;
+
+procedure TMemoComponentStrings.Insert(LineIndex: Integer; const S: string);
+var
+	Range: TCustomRange;
+begin
+	if Memo.TextLength > 0 then begin
+		Range := TMCRange.Create (nil);
+		with Range do begin
+			Editor := Memo;
+			if LineIndex < Memo.LineCount then begin
+				StartRowCol := TextCell (LineIndex + 1, 1);
+				RLength := 0;
+				Text := S + #13#10;
+			end else begin
+				RStart := Memo.TextLength + 1;
+				RLength := 0;
+				Text := #13#10 + S;
+			end;
+			Free;
+		end;
+	end else
+		Memo.Text := S;
+end;
+
+procedure TMemoComponentStrings.Put(LineIndex: Integer; const S: string);
+var
+	Range: TCustomRange;
+begin
+	Range := TMCRange.Create (nil);
+	with Range do begin
+		Editor := Memo;
+		StartRowCol := TextCell (LineIndex + 1, 1);
+		EndRowCol := TextCell (LineIndex + 2, -2);
+		Text := S;
+		Free;
+	end;
+end;
+
+procedure TMemoComponentStrings.SetTextStr(const Value: string);
+begin
+	Memo.Text := Value;
+end;
+
+{ TMCRanges }
+
+function TMCRanges.Add(Start, Count: Integer): TCustomRange;
+begin
+	Result := Add;
+	with Result do begin
+		RStart := Start;
+		RLength := Count;
+	end;
+end;
+
+function TMCRanges.Add: TCustomRange;
+begin
+	Result := FItemClass.Create(Self);
+end;
+
+constructor TMCRanges.Create(AOwner: TMemoComponent);
+begin
+	inherited Create (AOwner, TCustomRange);
+	FItemClass := TMCRange;
+end;
+
+destructor TMCRanges.Destroy;
+begin
+	FDestroying := True;
+	inherited;
+end;
+
+function TMCRanges.NewGetItem(ItemIndex: Integer): TCustomRange;
+begin
+	Result := TCustomRange (GetItem (ItemIndex));
+end;
+
+function TMCRanges.NewGetOwner: TMemoComponent;
+begin
+	Result := TMemoComponent (inherited Owner);
+end;
+
+{ TCustomRange }
+
+procedure TCustomRange.SetText(const Value: string);
+begin
+	if Assigned (Editor) then
+		Editor.ReplaceText (Self, Value);
+end;
+
+function TCustomRange.GetText: string;
+begin
+	if Assigned (Editor) then
+		Result := Copy (Editor.Text, RStart, RLength)
+	else
+		Result := '';
+end;
+
+function TCustomRange.GetEndRowCol: TTextCell;
+begin
+	if Assigned (Editor) then
+		Result := Editor.CharIdxToCell (REnd)
+	else
+		Result := TextCell (1, 0);
+end;
+
+function TCustomRange.GetStartRowCol: TTextCell;
+begin
+	if Assigned (Editor) then
+		Result := Editor.CharIdxToCell (RStart)
+	else
+		Result := TextCell (1, 1);
+end;
+
+procedure TCustomRange.SetEndRowCol(const Value: TTextCell);
+begin
+	if Assigned (Editor) then
+		REnd := Editor.CellToCharIdx (Value);
+end;
+
+procedure TCustomRange.SetStartRowCol(const Value: TTextCell);
+begin
+	if Assigned (Editor) then
+		RStart := Editor.CellToCharIdx (Value);
+end;
+
+function TCustomRange.GetRLength: Integer;
+begin
+	Result := REnd - RStart + 1;
+end;
+
+procedure TCustomRange.SetRLength(const Value: Integer);
+begin
+	REnd := RStart + Value - 1;
+end;
+
+procedure TCustomRange.SetREnd(const Value: Integer);
+begin
+end;
+
+procedure TCustomRange.SetRStart(const Value: Integer);
+begin
+end;
+
+procedure TCustomRange.NotifyOverwrite;
+begin
+	if Assigned (FOnOverwrite) then
+		FOnOverwrite (Self);
+end;
+
+procedure TCustomRange.Clear;
+begin
+	if RLength > 0 then
+		Text := '';
+end;
+
+function TCustomRange.CharInRange(CharIdx: Integer): Boolean;
+begin
+	Result := (CharIdx >= RStart) and (CharIdx <= REnd);
+end;
+
+procedure TCustomRange.DrawRange;
+var
+	Part: TMCRange;
+	I,
+	LC,
+	TR,
+	RowS,
+	RowE,
+	ColS,
+	ColE,
+	ScrCol: Integer;
+	AfterText: Boolean;
+	SC,
+	EC,
+	Cell: TTextCell;
+	Cnv: TCanvas;
+begin
+	if Assigned (Editor) and Editor.HandleAllocated and Assigned (Editor.Parent) and (Editor.VisibleRange.FChanging = 0) and (not (Editor.DrawingSuspended and not Editor.Bitmapped)) and ((RLength > 0) or (Self is TVisibleRange) or (Self is TWholeTextRange) or (RStart >= Editor.TextLength)) then begin
+		if Editor.Bitmapped then begin
+			Editor.UpdateDrawBmp;
+			Cnv := Editor.DrawBmp.Canvas;
+		end else begin
+			Cnv := Editor.Canvas;
+			if (RStart >= Editor.Selection.CursorPos - 1) and (REnd <= Editor.Selection.CursorPos) then
+				Editor.Selection.HideCaret;
+		end;
+		if Editor.TextLength <= 0 then begin
+			Cnv.Brush.Color := Editor.Color;
+			Cnv.FillRect (Editor.ClientRect)
+		end else begin
+			LC := Editor.VisibleRange.LeftCol;
+			TR := Editor.VisibleRange.TopRow;
+			SC := StartRowCol;
+			EC := EndRowCol;
+			Part := TMCRange.Create (nil);
+			Part.Editor := Editor;
+			RowS := SC.Row;
+			if RowS < TR then
+				RowS := TR;
+			RowE := EC.Row;
+			if REnd >= Editor.TextLength then
+				Inc (RowE);
+			I := TR + Editor.PageHeight + 1;
+			if Editor.VisibleRange.REnd >= Editor.TextLength then
+				Inc (I);
+			if RowE > I then
+				RowE := I;
+			for I := RowS to RowE do begin
+				if I = SC.Row then begin
+					ColS := SC.Col;
+					Cell := TextCell (I, Editor.CellToScrCol (SC))
+				end else begin
+					ColS := 1;
+					Cell := TextCell (I, 1);
+				end;
+				if Cell.Col < Editor.VisibleRange.LeftCol then
+					Cell.Col := Editor.VisibleRange.LeftCol;
+				ScrCol := Editor.CellFromScrColToScrCol (Cell);
+				if I = EC.Row then
+					ColE := EC.Col
+				else
+					ColE := Editor.LineLength [I] + 2;
+				if ColE > Editor.VisibleRange.RightCol then
+					ColE := Editor.VisibleRange.RightCol;
+				AfterText := (I >= Editor.LineCount) and (Editor.CellToCharIdx (TextCell (I, ColS - 1)) > Editor.TextLength);
+				if AfterText then begin
+					Part.StartRowCol := TextCell (I + 1, -1);
+					with Editor.Selection do
+						if CharInRange (Part.RStart) then begin
+							if Editor.HasFocus then
+								Cnv.Brush.Color := clHighlight
+							else
+								Cnv.Brush.Color := clSilver;
+						end else begin
+							Cnv.Brush.Color := Editor.Color;
+							if (RStart >= Part.RStart) and (RStart <= Part.RStart + 2) then
+								HideCaret;
+						end;
+					Cnv.FillRect (Rect (Editor.LeftMargin, Editor.TopMargin + (I - TR) * Editor.FontHeight, Editor.ClientWidth, Editor.TopMargin + (I - TR + 1) * Editor.FontHeight));
+				end else begin
+					if (ColE >= ColS) or ((I >= Editor.LineCount) and (Editor.CellToCharIdx (TextCell (I, ColE)) >= Editor.TextLength)) then begin
+						Part.StartRowCol := Cell;
+						Part.EndRowCol := TextCell (I, ColE);
+						Editor.DrawTextLine (Part, Editor.LeftMargin + (ScrCol - LC) * Editor.FontWidth, Editor.TopMargin + (I - TR) * Editor.FontHeight, Editor.TabSize - (ScrCol - 1) mod Editor.TabSize);
+					end;
+				end;
+				if (I >= Editor.LineCount) or AfterText then begin
+					if Editor.Selection.RStart >= Editor.TextLength then
+						Editor.Selection.HideCaret;
+					Cnv.Brush.Color := Editor.Color;
+					Cnv.FillRect (Rect (Editor.LeftMargin, Editor.TopMargin + (Editor.LineCount - TR + 1) * Editor.FontHeight, Editor.ClientWidth, Editor.ClientHeight));
+				end;
+			end;
+			Part.Free;
+		end;
+		if Editor.Bitmapped then
+			Editor.Invalidate
+		else
+			Editor.Selection.ShowCaret;
+	end;
+end;
+
+constructor TCustomRange.Create(Collection: TFastObjectContainer);
+begin
+	inherited;
+	if Collection is TMCRanges then
+		Editor := TMCRanges(Collection).Owner;
+end;
+
+procedure TCustomRange.Change;
+begin
+	if Assigned (FOnChange) then
+		FOnChange (Self);
+end;
+
+function TCustomRange.GetEndPoint: TPoint;
+var
+	Cell: TTextCell;
+	I: Integer;
+	Ps: Integer;
+begin
+	if Assigned (Editor) then begin
+		Cell := EndRowCol;
+		with Cell do begin
+			if (REnd > 0) and (REnd <= Editor.TextLength) and (Editor.Text [REnd] in [#10, #13]) then begin
+				Inc (Row);
+				Col := 0;
+			end;
+			if Editor.TabSize = 1 then
+				Ps := Col
+			else begin
+				Ps := 0;
+				for I := Editor.CellToCharIdx (TextCell (Row, 1)) to REnd do begin
+					if (I > 0) and (I <= Editor.TextLength) and (Editor.Text [I] = #9) then
+						Ps := (Ps div Editor.TabSize + 1) * Editor.TabSize
+					else
+						Inc (Ps);
+				end;
+			end;
+			with Editor.VisibleRange do
+				Result := Editor.ScrCellToScrPoint (TextCell (Row - TopRow + 1, Ps - LeftCol + 2))
+		end;
+	end else
+		Result := Point (0, 0);
+end;
+
+function TCustomRange.GetStartPoint: TPoint;
+var
+	Cell: TTextCell;
+	I: Integer;
+	Ps: Integer;
+begin
+	if Assigned (Editor) then begin
+		Cell := StartRowCol;
+		with Cell do begin
+			if Editor.TabSize = 1 then
+				Ps := Col - 1
+			else begin
+				Ps := 0;
+				for I := Editor.CellToCharIdx (TextCell (Row, 1)) to RStart - 1 do begin
+					if (I > 0) and (I <= Editor.TextLength) and (Editor.Text [I] = #9) then
+						Ps := (Ps div Editor.TabSize + 1) * Editor.TabSize
+					else
+						Inc (Ps);
+				end;
+			end;
+			with Editor.VisibleRange do
+				Result := Editor.ScrCellToScrPoint (TextCell (Row - TopRow + 1, Ps - LeftCol + 2))
+		end;
+	end else
+		Result := Point (0, 0);
+end;
+
+procedure TCustomRange.Changing;
+begin
+end;
+
+procedure TCustomRange.DoChange;
+begin
+	Dec (FChanging);
+	if FChanging = 0 then
+		Change;
+end;
+
+procedure TCustomRange.DoChanging;
+begin
+	if FChanging = 0 then
+		Changing;
+	Inc (FChanging);
+end;
+
+procedure TCustomRange.DiscardChanges;
+begin
+end;
+
+procedure TCustomRange.DoDiscardChanges;
+begin
+	Dec (FChanging);
+	if FChanging = 0 then
+		DiscardChanges;
+end;
+
+procedure TCustomRange.ScrollInView(FromBorder: Integer);
+var
+	Cell: TTextCell;
+	LC,
+	Tolerance: Integer;
+	U: Boolean;
+begin
+	if Assigned (Editor) then begin
+		if FromBorder < MaxScrollTolerance then
+			Tolerance := FromBorder
+		else
+			Tolerance := MaxScrollTolerance;
+		if (Self is TSelectionRange) and TSelectionRange(Self).Backwards then
+			Cell := StartRowCol
+		else
+			Cell := Editor.CharIdxToCell (REnd + 1);
+		Cell.Col := Editor.CellToScrCol (Cell);
+		with Editor.VisibleRange do begin
+			DoChanging;
+			U := True;
+			if TopRow > Cell.Row - Tolerance then
+				TopRow := Cell.Row - FromBorder
+			else if (TopRow < Cell.Row - Editor.PageHeight + 1) and (Editor.PageHeight > 1) then
+				TopRow := Cell.Row - Editor.PageHeight + 1 + FromBorder
+			else
+				U := False;
+			if LeftCol > Cell.Col - Tolerance then begin
+				LC := Cell.Col - FromBorder;
+				if LC < 1 then
+					LC := 1;
+				if LeftCol <> LC then begin
+					LeftCol := LC;
+					U := True;
+				end;
+			end else if LeftCol < Cell.Col - Editor.PageWidth then begin
+				LC := Cell.Col - Editor.PageWidth + FromBorder;
+				if LC < 1 then
+					LC := 1;
+				if LeftCol <> LC then begin
+					LeftCol := LC;
+					U := True;
+				end;
+			end;
+			if U then
+				DoChange
+			else
+				DoDiscardChanges;
+		end;
+	end;
+end;
+
+procedure TCustomRange.AssignTo(Dest: TPersistent);
+begin
+	if Dest is TCustomRange then begin
+		with Dest as TCustomRange do begin
+			DoChanging;
+			RStart := Self.RStart;
+			REnd := Self.REnd;
+			DoChange;
+		end;
+		Exit;
+	end;
+	inherited;
+end;
+
+procedure TCustomRange.InternalDoMove(RangeStart, RangeEnd, LC: Integer);
+var
+	RMod: Boolean;
+	RE: Integer;
+	AdjustRE: Boolean;
+begin
+	// Warning: The same function exists for TMCRange.
+	// See the comments for that procedure.
+	DoChanging;
+	RMod := False;
+	if LC > 0 then begin
+		if (REnd >= RangeStart) and (REnd <= RangeEnd) then begin
+			if RStart > RangeStart then
+				RStart := RangeStart;
+			REnd := RangeStart - 1;
+			RMod := True;
+		end else if REnd > RangeEnd then
+			REnd := REnd + LC;
+		if (RStart >= RangeStart) and (RStart <= RangeEnd) then begin
+			RStart := RangeStart;
+			RMod := True;
+		end else if RStart > RangeEnd then begin
+			if RStart <= REnd then
+				RStart := RStart + LC;
+		end;
+	end else begin
+		RE := REnd;
+		AdjustRE := False;
+		if (RStart >= RangeStart) and (RStart <= RangeEnd) then begin
+			RStart := RangeStart;
+			RMod := True;
+		end else if RStart > RangeEnd then begin
+			if (RStart > RE) and (RE = RangeEnd) then
+				AdjustRE := True;
+			RStart := RStart + LC;
+		end;
+		if (not AdjustRE) and (RE >= RangeStart) and (RE <= RangeEnd) then begin
+			if RStart > RangeStart then
+				RStart := RangeStart;
+			REnd := RangeStart - 1;
+			RMod := True;
+		end else if AdjustRE or (RE > RangeEnd) then
+			REnd := RE + LC;
+	end;
+	DoChange;
+	if RMod and (RLength <= 0) then
+		NotifyOverwrite;
+end;
+
+{ TMCRange }
+
+constructor TMCRange.Create(Collection: TFastObjectContainer);
+begin
+	inherited;
+	FRStart := 1;
+end;
+
+function TMCRange.GetREnd: Integer;
+begin
+	Result := FREnd;
+end;
+
+function TMCRange.GetRStart: Integer;
+begin
+	Result := FRStart;
+end;
+
+procedure TMCRange.InternalDoMove(RangeStart, RangeEnd, LC: Integer);
+var
+	RMod: Boolean;
+	RE: Integer;
+	AdjustRE: Boolean;
+begin
+	// Warning: The same function exists for TCustomRange.
+	DoChanging;
+	RMod := False;
+	if LC > 0 then begin
+		// Characters have been added to the range given by RangeStart and RangeEnd.
+		// First, adjust REnd.
+		if (FREnd >= RangeStart) and (FREnd <= RangeEnd) then begin
+			// The current range (Self) ends in the area that has been changed.
+			if FRStart > RangeStart then
+				// It also starts in the area, so let it start at the beginning.
+				FRStart := RangeStart;
+			// Let the range end at the last character that has stayed the same.
+			FREnd := RangeStart - 1;
+			// The current range has been 'overwritten'.
+			RMod := True;
+		end else if FREnd > RangeEnd then
+			// The current range ends behind the area that has been changed.
+			// No matter where it starts, it is moved by LC characters (LC > 0).
+			FREnd := FREnd + LC;
+		// Next, adjust RStart.
+		if (FRStart >= RangeStart) and (FRStart <= RangeEnd) then begin
+			// The current range (Self) starts in the area that has been changed.
+			// Let the range start at the beginning of the updated area.
+			FRStart := RangeStart;
+			// The current range has been 'overwritten'.
+			RMod := True;
+		end else if FRStart > RangeEnd then begin
+			// The current range starts behind the area that has been changed.
+			if FRStart <= FREnd then
+				// Special case: If the current range is empty, and REnd hasn't
+				// been moved to the right, then don't move RStart either.
+				// Otherwise, it is moved by LC characters (LC > 0).
+				FRStart := FRStart + LC;
+		end;
+	end else begin
+		// Characters have been removed from the range
+		// For TCustomRange, changing RStart may also change REnd; save REnd
+		// to avoid problems.
+		RE := FREnd;
+		AdjustRE := False;
+		// First, adjust RStart.
+		if (FRStart >= RangeStart) and (FRStart <= RangeEnd) then begin
+			// The current range (Self) starts in the area that has been changed.
+			// Let the range start at the beginning of the updated area.
+			FRStart := RangeStart;
+			// The current range has been 'overwritten'.
+			RMod := True;
+		end else if FRStart > RangeEnd then begin
+			// The current range starts behind the area that has been changed.
+			// No matter where it ends, it is moved by LC characters (LC <= 0).
+			if (FRStart > RE) and (RE = RangeEnd) then
+				// If the range is empty and starts directly after the changed area,
+				// REnd would normally not be adjusted correctly. So do this manually.
+				AdjustRE := True;
+			FRStart := FRStart + LC;
+		end;
+		if (not AdjustRE) and (RE >= RangeStart) and (RE <= RangeEnd) then begin
+			// The current range (Self) ends in the area that has been changed.
+			if FRStart > RangeStart then
+				FRStart := RangeStart;
+			// Let the range end at the last character that has stayed the same.
+			FREnd := RangeStart - 1;
+			// The current range has been 'overwritten'.
+			RMod := True;
+		end else if AdjustRE or (RE > RangeEnd) then
+			// The current range ends behind the area that has been changed.
+			// No matter where it starts, it is moved by LC characters (LC <= 0).
+			FREnd := RE + LC;
+	end;
+	DoChange;
+	if RMod and (FREnd < FRStart) then
+		// The range has been completely overwritten.
+		NotifyOverwrite;
+end;
+
+procedure TMCRange.SetREnd(const Value: Integer);
+begin
+	DoChanging;
+	FREnd := Value;
+	if FREnd < RStart - 1 then
+		FREnd := RStart - 1;
+	if Assigned (Editor) and (FREnd > Editor.TextLength) then
+		FREnd := Editor.TextLength;
+	DoChange;
+end;
+
+procedure TMCRange.SetRStart(const Value: Integer);
+begin
+	DoChanging;
+	FRStart := Value;
+	if FRStart < 1 then
+		FRStart := 1;
+	if Assigned (Editor) and (FRStart > Editor.TextLength + 1) then
+		FRStart := Editor.TextLength + 1;
+	REnd := REnd;
+	DoChange;
+end;
+
+{ TWholeTextRange }
+
+function TWholeTextRange.GetREnd: Integer;
+begin
+	if Assigned (Editor) then
+		Result := Editor.TextLength
+	else
+		Result := 0;
+end;
+
+function TWholeTextRange.GetRStart: Integer;
+begin
+	Result := 1;
+end;
+
+{ TVisibleRange }
+
+procedure TVisibleRange.Change;
+function DivDown(Div1, Div2: Integer): Integer;
+begin
+	Result := Div1 div Div2;
+end;
+function DivUp(Div1, Div2: Integer): Integer;
+begin
+	Result := (Div1 - 1) div Div2 + 1;
+end;
+var
+	NewTextRect,
+	EditorRect,
+	UpdateRect: TRect;
+begin
+	inherited;
+	if Assigned (Editor) and Editor.HandleAllocated then begin
+		NewTextRect := Rect (FLeftCol, FTopRow, FLeftCol + Editor.PageWidth + 1, FTopRow + Editor.PageHeight + 1);
+		if not EqualRect (VisibleTextRect, NewTextRect) then
+			with Editor.Selection do begin
+				HideCaret;
+				if (NewTextRect.Left <> VisibleTextRect.Left) or (NewTextRect.Top >= VisibleTextRect.Bottom - 1) or (VisibleTextRect.Top >= NewTextRect.Bottom - 1) then
+					Self.DrawRange
+				else with Editor do begin
+					EditorRect := ClientRect;
+					Inc (EditorRect.Left, Editor.LeftMargin);
+					Inc (EditorRect.Top, Editor.TopMargin);
+					if VisibleTextRect.Top <> NewTextRect.Top then begin
+						if Bitmapped and Assigned (DrawBmp) then begin
+							if VisibleTextRect.Top > NewTextRect.Top then begin
+								BitBlt (DrawBmp.Canvas.Handle, LeftMargin, TopMargin, DrawBmp.Width - LeftMargin, DrawBmp.Height - TopMargin - (NewTextRect.Top - VisibleTextRect.Top) * FontHeight, DrawBmp.Canvas.Handle, LeftMargin, TopMargin + (NewTextRect.Top - VisibleTextRect.Top) * FontHeight, SrcCopy);
+								UpdateRect := Rect (LeftMargin, TopMargin, ClientWidth, TopMargin + (VisibleTextRect.Top - NewTextRect.Top) * FontHeight);
+							end else begin
+								BitBlt (DrawBmp.Canvas.Handle, LeftMargin, TopMargin + (VisibleTextRect.Top - NewTextRect.Top) * FontHeight, DrawBmp.Width - LeftMargin, DrawBmp.Height - TopMargin - (VisibleTextRect.Top - NewTextRect.Top) * FontHeight, DrawBmp.Canvas.Handle, LeftMargin, TopMargin, SrcCopy);
+								UpdateRect := Rect (LeftMargin, ClientHeight - (NewTextRect.Top - VisibleTextRect.Top) * FontHeight, ClientWidth, ClientHeight);
+							end;
+						end else
+							ScrollWindowEx (Handle, 0, (VisibleTextRect.Top - NewTextRect.Top) * FontHeight, @EditorRect, @EditorRect, 0, @UpdateRect, 0);
+					end else
+						UpdateRect := Rect (0, 0, -1, -1);
+					if not IsRectEmpty (UpdateRect) then
+						with TMCRange.Create (nil) do begin
+							Editor := Self.Editor;
+							StartRowCol := TextCell (DivDown (UpdateRect.Top, FontHeight) + FTopRow, 1);
+							EndRowCol := TextCell (DivUp (UpdateRect.Bottom, FontHeight) + FTopRow, 1);
+							DrawRange;
+							Free;
+						end;
+					if Bitmapped and Assigned (DrawBmp) then
+						Invalidate;
+				end;
+				UpdateCaretPos;
+				ShowCaret;
+			end;
+		end;
+end;
+
+procedure TVisibleRange.Changing;
+begin
+	if Assigned (Editor) then
+		VisibleTextRect := Rect (FLeftCol, FTopRow, FLeftCol + Editor.PageWidth + 1, FTopRow + Editor.PageHeight + 1)
+	else
+		VisibleTextRect := Rect (0, 0, 0, 0);
+end;
+
+constructor TVisibleRange.Create(Collection: TFastObjectContainer);
+begin
+	inherited;
+	FTopRow := 1;
+	FLeftCol := 1;
+end;
+
+function TVisibleRange.GetBottomRow: Integer;
+begin
+	if Assigned (Editor) then
+		Result := TopRow + Editor.PageHeight + 1
+	else
+		Result := TopRow;
+end;
+
+function TVisibleRange.GetEndRowCol: TTextCell;
+begin
+	if Assigned (Editor) then begin
+		Result := TextCell (FTopRow + Editor.PageHeight + 1, 0);
+		if Editor.CellToCharIdx (Result) > Editor.TextLength then
+			Result := Editor.CharIdxToCell (Editor.TextLength);
+	end else
+		Result := TextCell (FTopRow, 0);
+end;
+
+function TVisibleRange.GetREnd: Integer;
+begin
+	if Assigned (Editor) then
+		Result := Editor.CellToCharIdx (EndRowCol)
+	else
+		Result := 0;
+end;
+
+function TVisibleRange.GetRightCol: Integer;
+begin
+	if Assigned (Editor) then
+		Result := LeftCol + Editor.PageWidth + 1
+	else
+		Result := LeftCol;
+end;
+
+function TVisibleRange.GetRStart: Integer;
+begin
+	if Assigned (Editor) then
+		Result := Editor.CellToCharIdx (StartRowCol)
+	else
+		Result := 1;
+end;
+
+function TVisibleRange.GetStartRowCol: TTextCell;
+begin
+	Result := TextCell (FTopRow, 1);
+end;
+
+procedure TVisibleRange.SetBottomRow(const Value: Integer);
+begin
+	if Assigned (Editor) then
+		TopRow := Value - Editor.PageHeight
+	else
+		TopRow := Value;
+end;
+
+procedure TVisibleRange.SetEndRowCol(const Value: TTextCell);
+begin
+end;
+
+procedure TVisibleRange.SetLeftCol(const Value: Integer);
+begin
+	if FLeftCol <> Value then begin
+		DoChanging;
+		FLeftCol := Value;
+		Update;
+		DoChange;
+	end;
+end;
+
+procedure TVisibleRange.SetREnd(const Value: Integer);
+begin
+end;
+
+procedure TVisibleRange.SetRightCol(const Value: Integer);
+begin
+	if Assigned (Editor) then
+		LeftCol := Value - Editor.PageWidth
+	else
+		LeftCol := Value;
+end;
+
+procedure TVisibleRange.SetRLength(const Value: Integer);
+begin
+end;
+
+procedure TVisibleRange.SetRStart(const Value: Integer);
+begin
+	if Assigned (Editor) then
+		StartRowCol := Editor.CharIdxToCell (Value);
+end;
+
+procedure TVisibleRange.SetStartRowCol(const Value: TTextCell);
+begin
+	TopRow := Value.Row;
+end;
+
+procedure TVisibleRange.SetTopRow(const Value: Integer);
+begin
+	if FTopRow <> Value then begin
+		DoChanging;
+		FTopRow := Value;
+		Update;
+		DoChange;
+	end;
+end;
+
+procedure TVisibleRange.Update;
+begin
+	if Assigned (Editor) and (FTopRow > Editor.LineCount - Editor.PageHeight + 1) then
+		FTopRow := Editor.LineCount - Editor.PageHeight + 1;
+	if FTopRow < 1 then
+		FTopRow := 1;
+	if Assigned (Editor) and (FLeftCol > Editor.LongestLineLength - Editor.PageWidth + 1) then
+		FLeftCol := Editor.LongestLineLength - Editor.PageWidth + 1;
+	if FLeftCol < 1 then
+		FLeftCol := 1;
+	if Assigned (Editor) and Editor.HandleAllocated then begin
+		SetScrollPos (Editor.Handle, sb_Vert, FTopRow, True);
+		SetScrollPos (Editor.Handle, sb_Horz, FLeftCol, True);
+	end;
+end;
+
+{ TSelectionRange }
+
+procedure TSelectionRange.AssignTo(Dest: TPersistent);
+begin
+	inherited;
+	if Dest is TSelectionRange then
+		with Dest as TSelectionRange do
+			Backwards := Self.Backwards;
+end;
+
+procedure TSelectionRange.Change;
+var
+	RS: Integer;
+begin
+	inherited;
+	if Assigned (FOldSel) then
+		with FOldSel do begin
+			if Assigned (Editor) and Editor.RemoveTrailingSpaces and (Self.StartRowCol.Row <> StartRowCol.Row) and (not Editor.FInUndo) then
+				Editor.RemoveTrSpFromLine (StartRowCol.Row);
+			if Self.RStart = RStart then begin
+				if Self.REnd > REnd then begin
+					RStart := REnd + 1;
+					REnd := Self.REnd;
+				end else
+					RStart := Self.REnd + 1;
+			end else if Self.REnd = REnd then begin
+				if Self.RStart < RStart then begin
+					RS := RStart;
+					RStart := Self.RStart;
+					REnd := RS - 1;
+				end else
+					REnd := Self.RStart - 1;
+			end else
+				if Self.RLength > 0 then
+					Self.DrawRange;
+			if RLength > 0 then
+				DrawRange;
+			Free;
+		end;
+	FOldSel := nil;
+	UpdateCaretPos;
+	ShowCaret;
+	if Assigned (Editor) then
+		Editor.SelectionChange;
+end;
+
+procedure TSelectionRange.Changing;
+begin
+	inherited;
+	HideCaret;
+	FScrCol := -1;
+	FOldSel := TMCRange.Create (nil);
+	FOldSel.Editor := Editor;
+	FOldSel.Assign (Self);
+end;
+
+procedure TSelectionRange.DiscardChanges;
+begin
+	inherited;
+	if Assigned (FOldSel) then
+		FOldSel.Free;
+	FOldSel := nil;
+	UpdateCaretPos;
+	ShowCaret;
+end;
+
+function TSelectionRange.GetCursorPos: Integer;
+begin
+	if Backwards then
+		Result := RStart
+	else
+		Result := REnd + 1;
+end;
+
+function TSelectionRange.GetScrCol: Integer;
+begin
+	if FScrCol <= 0 then begin
+		if Assigned (Editor) then
+			FScrCol := Editor.CellToScrCol (Editor.CharIdxToCell (CursorPos))
+		else
+			FScrCol := 1;
+	end;
+	Result := FScrCol;
+end;
+
+procedure TSelectionRange.HideCaret;
+begin
+	if Assigned (Editor) and Editor.FCaretCreated and FCaretShowing	and Editor.HandleAllocated then begin
+		Windows.HideCaret (Editor.Handle);
+		FCaretShowing := False;
+	end;
+end;
+
+procedure TSelectionRange.NoSelAtPos(Pos: Integer);
+begin
+	DoChanging;
+	Backwards := False;
+	RStart := Pos;
+	REnd := Pos - 1;
+	DoChange;
+end;
+
+function TSelectionRange.ScrColToCol(Row: Integer): Integer;
+var
+	Cell: TTextCell;
+begin
+	Cell.Row := Row;
+	Cell.Col := ScrCol;
+	if Assigned (Editor) then begin
+		Editor.CellFromScrCol (Cell);
+		if Cell.Col > Editor.LineLength [Row] + 1 then
+			Cell.Col := Editor.LineLength [Row] + 1;
+	end;
+	Result := Cell.Col;
+end;
+
+procedure TSelectionRange.SelectWord(Directions: TSelectWordDirections);
+var
+	WS,
+	WE: Integer;
+	S: string;
+begin
+	if Assigned (Editor) then begin
+		S := Editor.Text;
+		WS := RStart;
+		if swLeft in Directions then
+			while (WS > 1) and (IsCharAlphaNumeric (S [WS - 1]) or (S [WS - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'])) do
+				Dec (WS);
+		WE := REnd;
+		if swRight in Directions then
+			while (WE < Length (S)) and (IsCharAlphaNumeric (S [WE + 1]) or (S [WE + 1] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'])) do
+				Inc (WE);
+		RStart := WS;
+		REnd := WE;
+	end;
+end;
+
+procedure TSelectionRange.SetCursorPos(const Value: Integer);
+begin
+	if Backwards then begin
+		if Value <= REnd then
+			RStart := Value
+		else begin
+			Backwards := False;
+			RStart := REnd + 1;
+			REnd := Value - 1;
+		end;
+	end else begin
+		if Value - 1 >= RStart - 1 then
+			REnd := Value - 1
+		else begin
+			Backwards := True;
+			REnd := RStart - 1;
+			RStart := Value;
+		end;
+	end;
+end;
+
+procedure TSelectionRange.SetText(const Value: string);
+begin
+	if Assigned (Editor) then
+		with Editor do
+			if FSelecting then
+				MouseUp (mbLeft, [], 0, 0);
+	inherited;
+end;
+
+procedure TSelectionRange.ShowCaret;
+begin
+	if FChanging <= 0 then begin
+		if Assigned (Editor) and Editor.FCaretCreated and ((RLength = 0) or (Editor.AlwaysShowCaret)) and Editor.HasFocus and (not Editor.ReadOnly) and Editor.HandleAllocated then begin
+			if not FCaretShowing then begin
+				Windows.ShowCaret (Editor.Handle);
+				FCaretShowing := True;
+			end;
+		end else
+			HideCaret;
+	end;
+end;
+
+procedure TSelectionRange.UpdateCaretPos;
+var
+	P: TPoint;
+begin
+	if Assigned (Editor) and Editor.FCaretCreated and (FChanging <= 0) then begin
+		if Backwards then
+			P := StartPoint
+		else
+			P := EndPoint;
+		SetCaretPos (P.X - 1, P.Y + 1);
+	end;
+end;
+
+{ TCustomFormattedRange }
+
+procedure TCustomFormattedRange.AssignTo(Dest: TPersistent);
+begin
+	inherited;
+	if Dest is TCustomFormattedRange then
+		with Dest as TCustomFormattedRange do begin
+			Color := Self.Color;
+			Font := Self.Font;
+		end;
+end;
+
+procedure TCustomFormattedRange.CleanUpFont;
+begin
+	if Assigned (Editor) then
+		Font.Style := Font.Style - Editor.ForbiddenFontStyles;
+end;
+
+procedure TCustomFormattedRange.SetColor(const Value: TColor);
+begin
+end;
+
+procedure TCustomFormattedRange.SetFont(const Value: TFont);
+begin
+end;
+
+{ TFormattedRange }
+
+constructor TFormattedRange.Create(Collection: TFastObjectContainer);
+begin
+	inherited;
+	FFont := TFont.Create;
+end;
+
+destructor TFormattedRange.Destroy;
+begin
+	FFont.Free;
+	inherited;
+end;
+
+function TFormattedRange.GetColor: TColor;
+begin
+	Result := FColor;
+end;
+
+function TFormattedRange.GetFont: TFont;
+begin
+	Result := FFont;
+end;
+
+procedure TFormattedRange.SetColor(const Value: TColor);
+begin
+	FColor := Value;
+end;
+
+procedure TFormattedRange.SetFont(const Value: TFont);
+begin
+	if Assigned (Value) then
+		FFont.Assign (Value);
+end;
+
+{ TNormalFormattedRange }
+
+function TNormalFormattedRange.GetColor: TColor;
+begin
+	if Assigned (Editor) then
+		Result := Editor.Color
+	else
+		Result := clWindow;
+end;
+
+function TNormalFormattedRange.GetFont: TFont;
+begin
+	if Assigned (Editor) then
+		Result := Editor.Font
+	else
+		Result := nil;
+end;
+
+end.

+ 65 - 0
tigcc/components/Source Editor Readme.txt

@@ -0,0 +1,65 @@
+                       Source Editor Component
+                      =========================
+                    for Borland Delphi 4 or later
+
+                 Copyright (c) 2000 Sebastian Reichelt
+                          SebastianR@gmx.de
+
+
+TSourceEdit is a source editor control with several features that are
+useful for IDE programmers with Delphi knowledge.  It is based on
+TMemoComponent, which is completely home-made from scratch.  However,
+many useful properties and methods of TMemo have been implemented.
+
+All properties and methods should be self-explaining.  If you have any
+questions concerning their usage, feel free to ask me.
+
+
+Note that you should use the property Text instead of Lines to access
+the whole text.  To modify a piece of text at runtime, use the
+following code, or something similar:
+
+with TMCRange.Create (nil) do
+  try
+    Editor := MyComponent;  // or whatever the name is
+    RStart := S;            // the first character
+    REnd := E;              // the last character; can be < S
+    Text := NewText;        // the new text;
+  finally
+    Free;
+  end;
+
+Instead of RStart and REnd, you can also use StartRowCol, EndRowCol,
+and RLength.
+
+Line breaks are signaled by #13#10.
+
+You also can track positions in your code using ranges.  If you do the
+following:
+
+MyRange := TMCRange.Create (MyComponent.TrackedRanges);
+with MyRange do begin
+  RStart := S;
+  REnd := E;
+  OnOverwrite := MyOverwriteHandle;  // optional
+end;
+
+then MyRange will always be updated when the text changes, so that you
+can easily jump to the correct position of an error, the definition of
+an identifier, or wherever you want.  Just use:
+
+MyComponent.Selection.Assign (MyRange);
+
+and the range will be selected.
+
+
+For automatic saving and loading of TSyntaxColoring, a
+TSyntaxColoringCopy class has been created, whose instances can be
+passed to TStream.ReadComponent and TStream.WriteComponent.  Note that
+TStream is an abstract class; use TMemoryStream instead.  Then you can,
+for example, save your whole highlighting options in the registry.
+
+
+That's all I want to write for now.  Happy programming!
+
+Sebastian Reichelt

+ 2166 - 0
tigcc/components/SourceEditUnit.pas

@@ -0,0 +1,2166 @@
+
+{*******************************************************}
+{                                                       }
+{       TSourceEdit Component v2.19                     }
+{                                                       }
+{       Based on TMemoComponent                         }
+{                                                       }
+{       Copyright (c) 2000-2004 Sebastian Reichelt      }
+{                                                       }
+{*******************************************************}
+
+unit SourceEditUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, Consts, ObjList, MemoComponentUnit;
+
+const
+	SymbolChars: set of Char = ['<', '{', '[', '(', ')', ']', '}', '>', ';', ':', ',', '.', '=', '+', '-', '*', '/', '\', '|', '"', '''', '!', '?', '&', '%', '#', '@', '^', '~'];
+	MaxBeginEndTextLength  = 20;
+	CustomStyleCheckLength = 128;
+	MaxOnFlySectionLength  = 128;
+	SSourceEditError = 'TSourceEdit internal error';
+
+type
+	ESourceEdit = class(Exception);
+
+	TSyntaxColoring = class;
+	TWordLists = class;
+	TWordList = class;
+	TCustomStyles = class;
+	TCustomStyle = class;
+
+	TSyntaxRange = class;
+
+	TIgnoreChar = string [1];
+	TParenthesisStyle = (psOpening, psClosing);
+
+	TDebuggableRange = record
+		RStart,
+		REnd: Integer;
+		Text,
+		ClassName: string;
+	end;
+	TDebuggableRanges = array of TDebuggableRange;
+
+	TSourceEdit = class(TMemoComponent)
+	private
+		FSyntaxColoring: TSyntaxColoring;
+		FFirstSyntaxRange: TSyntaxRange;
+		FLastSyntaxRange: TSyntaxRange;
+		FAutoIndentIncrease: Boolean;
+		FAutoIndentIncreaseStart: Char;
+		FAutoIndentIncreaseEnd: Char;
+		FSplitOnFly: Boolean;
+		procedure CMFontChanged(var Message: TMessage); message cm_FontChanged;
+		procedure WMKeyDown(var Message: TWMKeyDown); message wm_KeyDown;
+		procedure SetSyntaxColoring(const Value: TSyntaxColoring);
+		procedure SetSplitOnFly(const Value: Boolean);
+	protected
+		SyntaxStartRange,
+		LastPRange: TSyntaxRange;
+		LastCRange: TCustomRange;
+		procedure KeyPress(var Key: Char); override;
+		procedure TextChangeNotification(StartPos, OldLength, NewLength: Integer); override;
+		procedure TextChangeNotificationAfter; override;
+		procedure ReColor; virtual;
+		procedure ReColorRange(Range: TCustomRange); virtual;
+		procedure FreeAllSyntaxRanges; virtual;
+		function ReplaceSyntaxRanges(NewRange: TSyntaxRange; var StartRange: TSyntaxRange): Boolean; virtual;
+		function CreateSplitRanges(Range: TCustomRange): TFormattedRangeArray; override;
+		procedure OverwriteRange(Sender: TObject);
+		function FindSyntaxHole: TSyntaxRange; virtual;
+		function FindSyntaxOverlap: TSyntaxRange; virtual;
+		function MakeDebuggableRanges: TDebuggableRanges; virtual;
+	public
+		constructor Create(AOwner: TComponent); override;
+		destructor Destroy; override;
+		function SyntaxRangeAtPos(RangePos: Integer): TSyntaxRange; virtual;
+		function SyntaxRangeAtPosWithHint(RangePos: Integer; Hint: TSyntaxRange): TSyntaxRange; virtual;
+		procedure RemoveTrSpFromString(var Str: string; IncludeLastLine: Boolean = False); override;
+		property FirstSyntaxRange: TSyntaxRange read FFirstSyntaxRange write FFirstSyntaxRange;
+		property LastSyntaxRange: TSyntaxRange read FLastSyntaxRange write FLastSyntaxRange;
+	published
+		property SyntaxColoring: TSyntaxColoring read FSyntaxColoring write SetSyntaxColoring;
+		property AutoIndentIncrease: Boolean read FAutoIndentIncrease write FAutoIndentIncrease;
+		property AutoIndentIncreaseStart: Char read FAutoIndentIncreaseStart write FAutoIndentIncreaseStart;
+		property AutoIndentIncreaseEnd: Char read FAutoIndentIncreaseEnd write FAutoIndentIncreaseEnd;
+		property SplitOnFly: Boolean read FSplitOnFly write SetSplitOnFly;
+	end;
+
+	TSyntaxRangeClass = class of TSyntaxRange;
+
+	TSyntaxRange = class(TCustomFormattedRange)
+	private
+		FParenthesisLevel: Integer;
+		FNextRange: TSyntaxRange;
+		FPrevRange: TSyntaxRange;
+	protected
+		procedure SetNewParenthesisLevel; virtual;
+		function GetNextParenthesisLevel: Integer; virtual;
+		function GetColor: TColor; override;
+		function ReplaceSyntaxRanges(var StartRange: TSyntaxRange): Boolean; virtual;
+	public
+		destructor Destroy; override;
+		class function EqualEndings(Range1, Range2: TSyntaxRange): Boolean;
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; virtual;
+		class function InsertRangeBefore(Range: TSyntaxRange; RangeClass: TSyntaxRangeClass; Editor: TSourceEdit): TSyntaxRange;
+		function InsertBefore(RangeClass: TSyntaxRangeClass): TSyntaxRange;
+		function InsertAfter(RangeClass: TSyntaxRangeClass): TSyntaxRange;
+		class function NewRangeInsertedBefore(Range: TSyntaxRange; Editor: TSourceEdit): TSyntaxRange;
+		class function NewRangeInsertedAfter(Range: TSyntaxRange; Editor: TSourceEdit): TSyntaxRange;
+		procedure UpdateParenthesisLevel; virtual;
+		property NextParenthesisLevel: Integer read GetNextParenthesisLevel;
+		property PrevRange: TSyntaxRange read FPrevRange write FPrevRange;
+		property NextRange: TSyntaxRange read FNextRange write FNextRange;
+	published
+		property ParenthesisLevel: Integer read FParenthesisLevel write FParenthesisLevel;
+	end;
+
+	TNormalTextRange = class(TSyntaxRange)
+	protected
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+	end;
+
+	TCustomStyleRange = class(TSyntaxRange)
+	private
+		FStyle: TCustomStyle;
+	protected
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+	published
+		property Style: TCustomStyle read FStyle write FStyle;
+	end;
+
+	TCustomTextRange = class(TSyntaxRange)
+	protected
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+	end;
+
+	TWordListRange = class(TSyntaxRange)
+	private
+		FWordList: TWordList;
+	protected
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+	published
+		property WordList: TWordList read FWordList write FWordList;
+	end;
+
+	TSymbolRange = class(TSyntaxRange)
+	private
+		FSymbol: string;
+	protected
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+	published
+		property Symbol: string read FSymbol write FSymbol;
+	end;
+
+	TNumberRange = class(TSyntaxRange)
+	private
+		FNumber: string;
+	protected
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+	published
+		property Number: string read FNumber write FNumber;
+	end;
+
+	TParenthesisRange = class(TSyntaxRange)
+	private
+		FStyle: TParenthesisStyle;
+	protected
+		procedure SetNewParenthesisLevel; override;
+		function GetNextParenthesisLevel: Integer; override;
+		function GetFont: TFont; override;
+	public
+		function EqualEndingsWith(Range: TSyntaxRange): Boolean; override;
+		procedure UpdateParenthesisLevel; override;
+	published
+		property Style: TParenthesisStyle read FStyle write FStyle;
+	end;
+
+	TSyntaxColoring = class(TOwnedPersistent)
+	private
+		FNumberColor: TColor;
+		FSymbolColor: TColor;
+		FCustomStyles: TCustomStyles;
+		FWordLists: TWordLists;
+		FEnabled: Boolean;
+		FUpdateDebth: Integer;
+		FParenthesisColors: TStringList;
+		FSymbolCustomStyle: Boolean;
+		FNumberCustomStyle: Boolean;
+		FNumberStyle: TFontStyles;
+		FSymbolStyle: TFontStyles;
+		FParenthesisCustomStyle: Boolean;
+		FParenthesisStyle: TFontStyles;
+		procedure SetCustomStyles(const Value: TCustomStyles);
+		procedure SetNumberColor(const Value: TColor);
+		procedure SetSymbolColor(const Value: TColor);
+		procedure SetWordLists(const Value: TWordLists);
+		procedure SetEnabled(const Value: Boolean);
+		procedure SetParenthesisColors(const Value: TStringList);
+		procedure SetNumberCustomStyle(const Value: Boolean);
+		procedure SetNumberStyle(const Value: TFontStyles);
+		procedure SetSymbolCustomStyle(const Value: Boolean);
+		procedure SetSymbolStyle(const Value: TFontStyles);
+		procedure SetParenthesisCustomStyle(const Value: Boolean);
+		procedure SetParenthesisStyle(const Value: TFontStyles);
+	protected
+		SymbolFont,
+		NumberFont,
+		ParenthesisFont: TFont;
+		procedure ChangeNotification(Sender: TObject);
+	public
+		constructor Create(AOwner: TPersistent); override;
+		destructor Destroy; override;
+		procedure ColoringChange; virtual;
+		procedure Assign(Source: TPersistent); override;
+		function GetParenthesisColor(Index: Integer): TColor;
+		procedure BeginUpdate; virtual;
+		procedure EndUpdate; virtual;
+	published
+		property Enabled: Boolean read FEnabled write SetEnabled;
+		property SymbolColor: TColor read FSymbolColor write SetSymbolColor;
+		property SymbolStyle: TFontStyles read FSymbolStyle write SetSymbolStyle;
+		property SymbolCustomStyle: Boolean read FSymbolCustomStyle write SetSymbolCustomStyle;
+		property NumberColor: TColor read FNumberColor write SetNumberColor;
+		property NumberStyle: TFontStyles read FNumberStyle write SetNumberStyle;
+		property NumberCustomStyle: Boolean read FNumberCustomStyle write SetNumberCustomStyle;
+		property WordLists: TWordLists read FWordLists write SetWordLists;
+		property CustomStyles: TCustomStyles read FCustomStyles write SetCustomStyles;
+		property ParenthesisColors: TStringList read FParenthesisColors write SetParenthesisColors;
+		property ParenthesisStyle: TFontStyles read FParenthesisStyle write SetParenthesisStyle;
+		property ParenthesisCustomStyle: Boolean read FParenthesisCustomStyle write SetParenthesisCustomStyle;
+	end;
+
+	TWordLists = class(TCollection)
+	private
+		FColoring: TSyntaxColoring;
+		function GetItem(Index: Integer): TWordList;
+		procedure SetItem(Index: Integer; Value: TWordList);
+	protected
+		function GetOwner: TPersistent; override;
+		procedure Update(Item: TCollectionItem); override;
+	public
+		constructor Create(AColoring: TSyntaxColoring);
+		function Add: TWordList;
+		function FindList(const S: string): TWordList;
+		property Items[Index: Integer]: TWordList read GetItem write SetItem; default;
+	end;
+
+	TWordList = class(TCollectionItem)
+	private
+		FCustomStyle: Boolean;
+		FCustomColor: Boolean;
+		FColor: TColor;
+		FStyle: TFontStyles;
+		FWords: TStringList;
+		FDisplayName: string;
+		FCaseSensitive: Boolean;
+		procedure SetColor(const Value: TColor);
+		procedure SetCustomColor(const Value: Boolean);
+		procedure SetCustomStyle(const Value: Boolean);
+		procedure SetStyle(const Value: TFontStyles);
+		procedure SetWords(const Value: TStringList);
+		procedure SetCaseSensitive(const Value: Boolean);
+	protected
+		Font: TFont;
+		function GetDisplayName: string; override;
+		procedure SetDisplayName(const Value: string); override;
+		procedure ListChange; virtual;
+		procedure ChangeNotification(Sender: TObject);
+	public
+		constructor Create(Collection: TCollection); override;
+		destructor Destroy; override;
+		procedure Assign(Source: TPersistent); override;
+		function WordInList(S: string): Boolean;
+	published
+		property Caption: string read FDisplayName write SetDisplayName;
+		property CustomColor: Boolean read FCustomColor write SetCustomColor;
+		property Color: TColor read FColor write SetColor;
+		property CustomStyle: Boolean read FCustomStyle write SetCustomStyle;
+		property Style: TFontStyles read FStyle write SetStyle;
+		property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
+		property Words: TStringList read FWords write SetWords;
+	end;
+
+	TCustomStyles = class(TCollection)
+	private
+		FColoring: TSyntaxColoring;
+		function GetItem(Index: Integer): TCustomStyle;
+		procedure SetItem(Index: Integer; Value: TCustomStyle);
+	protected
+		function GetOwner: TPersistent; override;
+		procedure Update(Item: TCollectionItem); override;
+	public
+		constructor Create(AColoring: TSyntaxColoring);
+		function Add: TCustomStyle;
+		function FindStyle(const S: string): TCustomStyle;
+		property Items[Index: Integer]: TCustomStyle read GetItem write SetItem; default;
+	end;
+
+	TCustomStyle = class(TCollectionItem)
+	private
+		FCustomStyle: Boolean;
+		FCustomColor: Boolean;
+		FEndText: string;
+		FBeginText: string;
+		FColor: TColor;
+		FStyle: TFontStyles;
+		FIgnoreChar: TIgnoreChar;
+		FDisplayName: string;
+		FSwitchable: Boolean;
+		FLineStartOnly: Boolean;
+    FIgnoreLeadingBlanks: Boolean;
+		procedure SetBeginText(Value: string);
+		procedure SetColor(const Value: TColor);
+		procedure SetCustomColor(const Value: Boolean);
+		procedure SetCustomStyle(const Value: Boolean);
+		procedure SetEndText(Value: string);
+		procedure SetIgnoreChar(const Value: TIgnoreChar);
+		procedure SetStyle(const Value: TFontStyles);
+		procedure SetSwitchable(const Value: Boolean);
+		procedure SetLineStartOnly(const Value: Boolean);
+    procedure SetIgnoreLeadingBlanks(const Value: Boolean);
+	protected
+		Font: TFont;
+		function GetDisplayName: string; override;
+		procedure SetDisplayName(const Value: string); override;
+		procedure StyleChange; virtual;
+	public
+		constructor Create(Collection: TCollection); override;
+		destructor Destroy; override;
+		procedure Assign(Source: TPersistent); override;
+	published
+		property Caption: string read FDisplayName write SetDisplayName;
+		property CustomColor: Boolean read FCustomColor write SetCustomColor;
+		property Color: TColor read FColor write SetColor;
+		property CustomStyle: Boolean read FCustomStyle write SetCustomStyle;
+		property Style: TFontStyles read FStyle write SetStyle;
+		property BeginText: string read FBeginText write SetBeginText;
+		property EndText: string read FEndText write SetEndText;
+		property IgnoreChar: TIgnoreChar read FIgnoreChar write SetIgnoreChar;
+		property Switchable: Boolean read FSwitchable write SetSwitchable;
+		property LineStartOnly: Boolean read FLineStartOnly write SetLineStartOnly;
+		property IgnoreLeadingBlanks: Boolean read FIgnoreLeadingBlanks write SetIgnoreLeadingBlanks;
+	end;
+
+	TSyntaxColoringCopy = class(TComponent)
+	private
+		FNumberColor: TColor;
+		FSymbolColor: TColor;
+		FCustomStyles: TCustomStyles;
+		FWordLists: TWordLists;
+		FEnabled: Boolean;
+		FParenthesisColors: TStringList;
+		FSymbolCustomStyle: Boolean;
+		FNumberCustomStyle: Boolean;
+		FNumberStyle: TFontStyles;
+		FSymbolStyle: TFontStyles;
+		FParenthesisCustomStyle: Boolean;
+		FParenthesisStyle: TFontStyles;
+		procedure SetCustomStyles(const Value: TCustomStyles);
+		procedure SetParenthesisColors(const Value: TStringList);
+		procedure SetWordLists(const Value: TWordLists);
+	protected
+	public
+		procedure Assign(Source: TPersistent); override;
+	published
+		constructor Create(AOwner: TComponent); override;
+		destructor Destroy; override;
+		property Enabled: Boolean read FEnabled write FEnabled;
+		property SymbolColor: TColor read FSymbolColor write FSymbolColor;
+		property SymbolStyle: TFontStyles read FSymbolStyle write FSymbolStyle;
+		property SymbolCustomStyle: Boolean read FSymbolCustomStyle write FSymbolCustomStyle;
+		property NumberColor: TColor read FNumberColor write FNumberColor;
+		property NumberStyle: TFontStyles read FNumberStyle write FNumberStyle;
+		property NumberCustomStyle: Boolean read FNumberCustomStyle write FNumberCustomStyle;
+		property WordLists: TWordLists read FWordLists write SetWordLists;
+		property CustomStyles: TCustomStyles read FCustomStyles write SetCustomStyles;
+		property ParenthesisColors: TStringList read FParenthesisColors write SetParenthesisColors;
+		property ParenthesisStyle: TFontStyles read FParenthesisStyle write FParenthesisStyle;
+		property ParenthesisCustomStyle: Boolean read FParenthesisCustomStyle write FParenthesisCustomStyle;
+	end;
+
+	TSectionType = (stText, stSymbol, stParenthesis, stCustomStyle);
+
+function CharIsWordable(Ch: Char): Boolean;
+function CharIsIdentifier(Ch: Char): Boolean;
+function CharIsExtNumber(Ch: Char): Boolean;
+function CharIsNumber(Ch: Char): Boolean;
+function CharIsSymbol(Ch: Char): Boolean;
+function CharIsParenthesis(Ch: Char): Boolean;
+
+procedure Register;
+
+implementation
+
+uses
+	UtilsDos;
+
+function CharIsWordable(Ch: Char): Boolean;
+begin
+	Result := CharIsIdentifier (Ch) or (Ch in ['#', '.', '+', '-']);
+end;
+
+function CharIsIdentifier(Ch: Char): Boolean;
+begin
+	Result := Ch in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'];
+end;
+
+function CharIsExtNumber(Ch: Char): Boolean;
+begin
+	Result := CharIsNumber (Ch) or (Ch in ['#', '.']);
+end;
+
+function CharIsNumber(Ch: Char): Boolean;
+begin
+	Result := Ch in ['0'..'9'];
+end;
+
+function CharIsHexNumber(Ch: Char): Boolean;
+begin
+	Result := Ch in ['A'..'F', 'a'..'f', '0'..'9'];
+end;
+
+function CharIsSymbol(Ch: Char): Boolean;
+begin
+	Result := Ch in SymbolChars;
+end;
+
+function CharIsParenthesis(Ch: Char): Boolean;
+begin
+	Result := Ch in ['(', ')'];
+end;
+
+procedure Register;
+begin
+	RegisterComponents ('Edit Controls', [TSourceEdit]);
+end;
+
+{ TSourceEdit }
+
+procedure TSourceEdit.CMFontChanged(var Message: TMessage);
+begin
+	inherited;
+	if Assigned (SyntaxColoring) then
+		SyntaxColoring.ColoringChange;
+end;
+
+constructor TSourceEdit.Create(AOwner: TComponent);
+begin
+	inherited;
+	FSyntaxColoring := TSyntaxColoring.Create (Self);
+	AutoIndent := True;
+	FAutoIndentIncrease := False;
+	FAutoIndentIncreaseStart := '{';
+	FAutoIndentIncreaseEnd := '}';
+	FSplitOnFly := False;
+end;
+
+function TSourceEdit.CreateSplitRanges(Range: TCustomRange): TFormattedRangeArray;
+var
+	RS,
+	RE,
+	TotalEnd: Integer;
+	ExitHere: Boolean;
+procedure AddRange(R: TCustomFormattedRange; AlwaysCopy: Boolean);
+procedure UpdateRS;
+begin
+	RS := RE + 1;
+	if RS < Range.RStart then
+		RS := Range.RStart;
+	if RS < R.RStart then
+		RS := R.RStart;
+end;
+procedure SetRE(NewValue: Integer);
+begin
+	if NewValue < RE then
+		NewValue := RE;
+	RE := NewValue;
+	if RE > Range.REnd then
+		RE := Range.REnd;
+	if RE > R.REnd then
+		RE := R.REnd;
+end;
+begin
+	UpdateRS;
+	if Selection.RLength > 0 then begin
+		SetRE (Selection.RStart - 1);
+		if RE >= RS then begin
+			SetLength (Result, Length (Result) + 1);
+			if AlwaysCopy or (RS <> R.RStart) or (RE <> R.REnd) then begin
+				Result [High (Result)] := TFormattedRange.Create (nil);
+				with Result [High (Result)] do begin
+					FreeWhenDone := True;
+					Editor := Self;
+					RStart := RS;
+					REnd := RE;
+					Font := R.Font;
+					Color := Self.Color;
+				end;
+			end else
+				Result [High (Result)] := R;
+		end;
+		UpdateRS;
+		SetRE (Selection.REnd);
+		if RE >= RS then begin
+			SetLength (Result, Length (Result) + 1);
+			Result [High (Result)] := TFormattedRange.Create (nil);
+			with Result [High (Result)] do begin
+				FreeWhenDone := True;
+				Editor := Self;
+				RStart := RS;
+				REnd := RE;
+				Font := R.Font;
+				if HasFocus then begin
+					Font.Color := clHighlightText;
+					Color := clHighlight;
+				end else
+					Color := clSilver;
+			end;
+		end;
+		UpdateRS;
+	end;
+	SetRE (R.REnd);
+	if RE >= RS then begin
+		SetLength (Result, Length (Result) + 1);
+		if AlwaysCopy or (RS <> R.RStart) or (RE <> R.REnd) then begin
+			Result [High (Result)] := TFormattedRange.Create (nil);
+			with Result [High (Result)] do begin
+				FreeWhenDone := True;
+				Editor := Self;
+				RStart := RS;
+				REnd := RE;
+				Font := R.Font;
+				Color := Self.Color;
+			end;
+		end else
+			Result [High (Result)] := R;
+	end;
+	if R.REnd >= TotalEnd then
+		ExitHere := True;
+end;
+var
+	I,
+	J,
+	LastStart: Integer;
+	CurWord: string;
+	IsNum: Boolean;
+	WordStyle: TWordList;
+	R: TCustomFormattedRange;
+begin
+	if SyntaxColoring.Enabled then begin
+		ExitHere := False;
+		TotalEnd := Range.REnd;
+		SyntaxStartRange := SyntaxRangeAtPosWithHint (Range.RStart, SyntaxStartRange);
+		RE := Range.RStart - 1;
+		while Assigned (SyntaxStartRange) and (SyntaxStartRange.RStart <= Range.REnd) do begin
+			if SyntaxStartRange is TCustomTextRange then begin
+				CurWord := '';
+				LastStart := SyntaxStartRange.RStart;
+				for I := SyntaxStartRange.RStart to SyntaxStartRange.REnd + 1 do begin
+					if I >= LastStart then begin
+						if (I <= SyntaxStartRange.REnd) and CharIsWordable (Text [I]) and ((not CharIsSymbol (Text [I]) or ((Text [I] = '.') and (((Length (CurWord) <= 0) and (I + 1 <= Length (Text)) and CharIsNumber (Text [I + 1])) or ((Length (CurWord) > 0) and CharIsExtNumber (CurWord [1])))))) then
+							CurWord := CurWord + Text [I]
+						else begin
+							if Length (CurWord) > 0 then begin
+								IsNum := CharIsExtNumber (CurWord [1]);
+								if (not IsNum) and (CurWord [1] = '$') and (Length (CurWord) > 1) then begin
+									IsNum := True;
+									for J := 2 to Length (CurWord) do
+										if not CharIsHexNumber (CurWord [J]) then begin
+											IsNum := False;
+											Break;
+										end;
+								end;
+								if IsNum then begin
+									if I - Length (CurWord) > LastStart then begin
+										R := TNormalTextRange.Create (nil);
+										with R do try
+											Editor := Self;
+											RStart := LastStart;
+											REnd := I - Length (CurWord) - 1;
+											if RLength > 0 then
+												AddRange (R, True);
+										finally
+											Free;
+										end;
+									end;
+									R := TNumberRange.Create (nil);
+									with R as TNumberRange do try
+										Editor := Self;
+										RStart := I - Length (CurWord);
+										REnd := I - 1;
+										Number := Text;
+										if RLength > 0 then
+											AddRange (R, True);
+										LastStart := I;
+									finally
+										Free;
+									end;
+								end else begin
+									WordStyle := SyntaxColoring.WordLists.FindList (CurWord);
+									if Assigned (WordStyle) then begin
+										if I - Length (CurWord) > LastStart then begin
+											R := TNormalTextRange.Create (nil);
+											with R do try
+												Editor := Self;
+												RStart := LastStart;
+												REnd := I - Length (CurWord) - 1;
+												if RLength > 0 then
+													AddRange (R, True);
+											finally
+												Free;
+											end;
+										end;
+										R := TWordListRange.Create (nil);
+										with R as TWordListRange do try
+											Editor := Self;
+											RStart := I - Length (CurWord);
+											REnd := I - 1;
+											WordList := WordStyle;
+											if RLength > 0 then
+												AddRange (R, True);
+											LastStart := I;
+										finally
+											Free;
+										end;
+									end;
+								end;
+								CurWord := '';
+							end;
+							if (I <= SyntaxStartRange.REnd) and CharIsSymbol (Text [I]) then begin
+								if I > LastStart then begin
+									R := TNormalTextRange.Create (nil);
+									with R do try
+										Editor := Self;
+										RStart := LastStart;
+										REnd := I - 1;
+										if RLength > 0 then
+											AddRange (R, True);
+									finally
+										Free;
+									end;
+								end;
+								R := TSymbolRange.Create (nil);
+								with R as TSymbolRange do try
+									Editor := Self;
+									RStart := I;
+									LastStart := I;
+									while (LastStart <= SyntaxStartRange.REnd) and CharIsSymbol (Self.Text [LastStart]) do
+										Inc (LastStart);
+									REnd := LastStart - 1;
+									Symbol := Text;
+									if RLength > 0 then
+										AddRange (R, True);
+								finally
+									Free;
+								end;
+							end;
+							if (I > SyntaxStartRange.REnd) and (I > LastStart) then begin
+								R := TNormalTextRange.Create (nil);
+								with R do try
+									Editor := Self;
+									RStart := LastStart;
+									REnd := I - 1;
+									LastStart := I;
+									if RLength > 0 then
+										AddRange (R, True);
+								finally
+									Free;
+								end;
+							end;
+						end;
+						if ExitHere then
+							Break;
+					end;
+				end;
+			end else
+				AddRange (SyntaxStartRange, False);
+			SyntaxStartRange := SyntaxStartRange.NextRange;
+		end;
+	end else
+		Result := inherited CreateSplitRanges (Range);
+	{$IFDEF SyntaxDebug}
+		for I := Low (Result) + 1 to High (Result) do
+			if Result[I-1].REnd + 1 <> Result[I].RStart then
+				raise ESourceEdit.Create (SSourceEditError);
+	{$ENDIF}
+end;
+
+destructor TSourceEdit.Destroy;
+begin
+	if Assigned (FSyntaxColoring) then begin
+		FSyntaxColoring.FUpdateDebth := 100;
+		FSyntaxColoring.Free;
+	end;
+	inherited;
+end;
+
+function TSourceEdit.FindSyntaxHole: TSyntaxRange;
+begin
+	Result := FirstSyntaxRange;
+	if Assigned (Result) and (Result.RStart = 1) then begin
+		if LastSyntaxRange.REnd <> TextLength then
+			Result := LastSyntaxRange
+		else
+			while Assigned (Result) and ((not Assigned (Result.NextRange)) or (Result.REnd + 1 = Result.NextRange.RStart)) do
+				Result := Result.NextRange;
+	end;
+end;
+
+function TSourceEdit.FindSyntaxOverlap: TSyntaxRange;
+begin
+	Result := FirstSyntaxRange;
+	while Assigned (Result) and ((not Assigned (Result.NextRange)) or (Result.REnd < Result.NextRange.RStart)) do
+		Result := Result.NextRange;
+end;
+
+procedure TSourceEdit.FreeAllSyntaxRanges;
+begin
+	while Assigned (LastSyntaxRange) do
+		LastSyntaxRange.Free;
+end;
+
+procedure TSourceEdit.KeyPress(var Key: Char);
+var
+	InsS: string;
+	Rs,
+	BeginLn,
+	FirstChr: Integer;
+begin
+	if (Key = #13) and AutoIndent then
+		with Selection do
+			if AutoIndentIncrease and (RStart - 1 > 0) and (RStart - 1 <= TextLength) and (Self.Text [RStart - 1] = AutoIndentIncreaseStart) and (RStart - 2 > 0) and (not (Self.Text [RStart - 2] in [#9, #10, #13])) then begin
+				BeginLn := CellToCharIdx (TextCell (StartRowCol.Row, 1));
+				FirstChr := FirstNonWhiteSpace (Copy (Self.Text, BeginLn, RStart - BeginLn));
+				InsS := #13#10 + Copy (Self.Text, BeginLn, FirstChr - 1) + #9;
+				RS := RStart;
+				Text := InsS + #13#10 + Copy (Self.Text, BeginLn, FirstChr - 1) + AutoIndentIncreaseEnd;
+				NoSelAtPos (RS + Length (InsS));
+				ScrollInView (4);
+				Key := #0;
+			end;
+	if (Key = AutoIndentIncreaseStart) and AutoIndentIncrease then begin
+		BeginLn := CellToCharIdx (TextCell (Selection.StartRowCol.Row, 1));
+		FirstChr := FirstNonWhiteSpace (Copy (Text, BeginLn, Selection.RStart - BeginLn));
+		if (BeginLn + FirstChr - 1 > TextLength) or (Text [BeginLn + FirstChr - 1] = #13) then begin
+			InsS := Key + #13#10 + Copy (Self.Text, BeginLn, FirstChr - 1) + #9;
+			with Selection do begin
+				RS := RStart;
+				Text := InsS + #13#10 + Copy (Self.Text, BeginLn, FirstChr - 1) + AutoIndentIncreaseEnd;
+				NoSelAtPos (RS + Length (InsS));
+				ScrollInView (4);
+			end;
+			Key := #0;
+		end;
+	end;
+	inherited;
+end;
+
+function TSourceEdit.MakeDebuggableRanges: TDebuggableRanges;
+var
+	Range: TSyntaxRange;
+begin
+	Range := FirstSyntaxRange;
+	while Assigned (Range) do begin
+		SetLength (Result, Length (Result) + 1);
+		with Result [High (Result)] do begin
+			RStart := Range.RStart;
+			REnd := Range.REnd;
+			Text := Range.Text;
+			ClassName := Range.ClassName;
+		end;
+		Range := Range.NextRange;
+	end;
+end;
+
+procedure TSourceEdit.OverwriteRange(Sender: TObject);
+begin
+	Sender.Free;
+end;
+
+procedure TSourceEdit.ReColor;
+begin
+	if TextLength > 0 then begin
+		Selection.HideCaret;
+		FreeAllSyntaxRanges;
+		ReColorRange (WholeText);
+		while Assigned (LastPRange) do begin
+			LastPRange.SetNewParenthesisLevel;
+			LastPRange := LastPRange.NextRange;
+		end;
+		VisibleRange.DrawRange;
+		Selection.UpdateCaretPos;
+		Selection.ShowCaret;
+	end;
+end;
+
+procedure TSourceEdit.ReColorRange(Range: TCustomRange);
+var
+	LastRange: TSyntaxRange;
+	KeepRunning,
+	EndingsEqual: Boolean;
+	SectionStart,
+	SectionLength,
+	WordStart,
+	CurPos: Integer;
+	CustomStyle,
+	NewCustomStyle: TCustomStyle;
+	CurChar: Char;
+	SectionType: TSectionType;
+procedure ProcessSection;
+var
+	I,
+	J,
+	LastStart: Integer;
+	CurWord: string;
+	IsNum: Boolean;
+	WordStyle: TWordList;
+begin
+	if SectionLength > 0 then begin
+		case SectionType of
+			stSymbol:
+				with TSymbolRange (TSymbolRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+					RStart := SectionStart;
+					RLength := SectionLength;
+					Symbol := Text;
+					EndingsEqual := ReplaceSyntaxRanges (LastRange);
+				end;
+			stParenthesis:
+				with TParenthesisRange (TParenthesisRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+					RStart := SectionStart;
+					RLength := SectionLength;
+					if Self.Text [SectionStart] in [')', '}', ']'] then
+						Style := psClosing
+					else
+						Style := psOpening;
+					EndingsEqual := ReplaceSyntaxRanges (LastRange);
+				end;
+			stCustomStyle:
+				with TCustomStyleRange (TCustomStyleRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+					RStart := SectionStart;
+					RLength := SectionLength;
+					Style := CustomStyle;
+					EndingsEqual := ReplaceSyntaxRanges (LastRange);
+				end;
+			stText: begin
+				if SplitOnFly then
+					with TCustomTextRange (TCustomTextRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+						RStart := SectionStart;
+						RLength := SectionLength;
+						EndingsEqual := ReplaceSyntaxRanges (LastRange);
+					end
+				else begin
+					CurWord := '';
+					LastStart := SectionStart;
+					for I := SectionStart to SectionStart + SectionLength do begin
+						if (I < SectionStart + SectionLength) and CharIsWordable (Text [I]) then
+							Insert (Text [I], CurWord, Length (CurWord) + 1)
+						else begin
+							if Length (CurWord) > 0 then begin
+								IsNum := CharIsExtNumber (CurWord [1]);
+								if (not IsNum) and (CurWord [1] = '$') and (Length (CurWord) > 1) then begin
+									IsNum := True;
+									for J := 2 to Length (CurWord) do
+										if not CharIsHexNumber (CurWord [J]) then begin
+											IsNum := False;
+											Break;
+										end;
+								end;
+								if IsNum then begin
+									if I - Length (CurWord) > LastStart then
+										with TNormalTextRange (TNormalTextRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+											RStart := LastStart;
+											REnd := I - Length (CurWord) - 1;
+											if RLength > 0 then
+												EndingsEqual := ReplaceSyntaxRanges (LastRange)
+											else
+												Free;
+										end;
+									with TNumberRange (TNumberRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+										RStart := I - Length (CurWord);
+										REnd := I - 1;
+										Number := Text;
+										EndingsEqual := ReplaceSyntaxRanges (LastRange);
+										LastStart := I;
+									end;
+								end else begin
+									WordStyle := SyntaxColoring.WordLists.FindList (CurWord);
+									if Assigned (WordStyle) then begin
+										if I - Length (CurWord) > LastStart then
+											with TNormalTextRange (TNormalTextRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+												RStart := LastStart;
+												REnd := I - Length (CurWord) - 1;
+												if RLength > 0 then
+													EndingsEqual := ReplaceSyntaxRanges (LastRange)
+												else
+													Free;
+											end;
+										with TWordListRange (TWordListRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+											RStart := I - Length (CurWord);
+											REnd := I - 1;
+											WordList := WordStyle;
+											EndingsEqual := ReplaceSyntaxRanges (LastRange);
+											LastStart := I;
+										end;
+									end;
+								end;
+								CurWord := '';
+							end;
+							if (I >= SectionStart + SectionLength) and (I > LastStart) then
+								with TNormalTextRange (TNormalTextRange.NewRangeInsertedBefore (LastRange, Self)) do begin
+									RStart := LastStart;
+									REnd := I - 1;
+									LastStart := I;
+									if RLength > 0 then
+										EndingsEqual := ReplaceSyntaxRanges (LastRange)
+									else
+										Free;
+								end;
+						end;
+					end;
+				end;
+			end;
+		end;
+	end;
+end;
+procedure SetSectionType(NewType: TSectionType);
+begin
+	if SplitOnFly and (NewType = stSymbol) and (SectionLength <= MaxOnFlySectionLength) then
+		NewType := stText;
+	if (NewType <> SectionType) or (NewType = stParenthesis) or (NewType = stCustomStyle) then begin
+		if SplitOnFly and (NewType = stSymbol) then
+			NewType := stText;
+		ProcessSection;
+		SectionStart := CurPos;
+		SectionLength := 0;
+		WordStart := CurPos;
+		SectionType := NewType;
+	end;
+end;
+function LeadingTextOnlyHasBlanks: Boolean;
+var
+	I: Integer;
+begin
+	Result := True;
+	I := CurPos - 1;
+	while I >= 1 do begin
+		if Text [I] in [#10, #13] then
+			Break;
+		if not (Text [I] in [#9, ' ']) then begin
+			Result := False;
+			Break;
+		end;
+		Dec (I);
+	end;
+end;
+var
+	I,
+	L,
+	P1,
+	P2,
+	BeginPos: Integer;
+	B: Boolean;
+	S,
+	T: string;
+begin
+	if SyntaxColoring.FUpdateDebth = 0 then begin
+		if SyntaxColoring.Enabled and (TextLength > 0) then begin
+			Inc (SyntaxColoring.FUpdateDebth);
+			LastRange := SyntaxRangeAtPos (Range.RStart - 1);
+			if Assigned (LastRange) then begin
+				if Assigned (LastRange.PrevRange) and (LastRange.PrevRange is TCustomStyleRange) and Assigned ((LastRange.PrevRange as TCustomStyleRange).Style) and (LastRange.PrevRange as TCustomStyleRange).Style.Switchable then
+					LastRange := LastRange.PrevRange;
+				if Range.RStart > LastRange.RStart then
+					Range.RStart := LastRange.RStart;
+			end else
+				Range.RStart := 1;
+			CurPos := Range.RStart;
+			SectionStart := CurPos;
+			SectionLength := 0;
+			WordStart := CurPos;
+			SectionType := stText;
+			CustomStyle := nil;
+			EndingsEqual := False;
+			KeepRunning := False;
+			while (CurPos <= TextLength) and ((CurPos <= Range.REnd + 2) or (not EndingsEqual) or KeepRunning) do begin
+				EndingsEqual := False;
+				CurChar := Text [CurPos];
+				NewCustomStyle := SyntaxColoring.CustomStyles.FindStyle (Copy (Text, CurPos, MaxBeginEndTextLength));
+				if Assigned (NewCustomStyle) and NewCustomStyle.LineStartOnly and (CurPos - 1 > 0) and (not (Text [CurPos - 1] in [#10, #13])) and ((not NewCustomStyle.IgnoreLeadingBlanks) or LeadingTextOnlyHasBlanks) then
+					NewCustomStyle := nil;
+				if Assigned (NewCustomStyle) and ((SectionType = stCustomStyle) and Assigned (CustomStyle) and (((NewCustomStyle = CustomStyle) and CustomStyle.Switchable) or (NewCustomStyle.EndText <> CustomStyle.EndText))) then
+					NewCustomStyle := nil;
+				KeepRunning := (SectionType = stCustomStyle) and Assigned (CustomStyle) and CustomStyle.Switchable and (not Assigned (NewCustomStyle));
+				if KeepRunning then begin
+					T := CustomStyle.EndText;
+					S := Copy (Text, CurPos, Length (T));
+					if (S = T) or ((T = ' ') and ((S = #9) or (S = #13))) then begin
+						KeepRunning := False;
+						I := CurPos - 1;
+						while (I >= 1) and ((Text [I] = CustomStyle.IgnoreChar) or ((CustomStyle.IgnoreChar = '\') and (Copy (Text, I - 2, 3) = '??/'))) do begin
+							KeepRunning := not KeepRunning;
+							if Text [I] = CustomStyle.IgnoreChar then
+								Dec (I)
+							else
+								Dec (I, 3);
+						end;
+					end;
+				end;
+				if not KeepRunning then begin
+					if Assigned (NewCustomStyle) then begin
+						SetSectionType (stCustomStyle);
+						CustomStyle := NewCustomStyle;
+						if CustomStyle.Switchable then begin
+							KeepRunning := True;
+							Inc (SectionLength);
+							Inc (CurPos);
+						end else begin
+							repeat
+								S := CustomStyle.EndText;
+								BeginPos := CurPos + Length (CustomStyle.BeginText);
+								repeat
+									T := Copy (Text, BeginPos, CustomStyleCheckLength);
+									P1 := Pos (S, T);
+									if S = ' ' then begin
+										P2 := Pos (#9, T);
+										if (P2 > 0) and ((P1 <= 0) or (P2 < P1)) then
+											P1 := P2;
+										P2 := Pos (#13, T);
+										if (P2 > 0) and ((P1 <= 0) or (P2 < P1)) then begin
+											P1 := P2;
+											S := #13;
+										end;
+									end;
+									if P1 <= 0 then
+										Inc (BeginPos, CustomStyleCheckLength - MaxBeginEndTextLength);
+								until (P1 > 0) or (BeginPos > TextLength);
+								CurPos := BeginPos + P1 + Length (S) - 2;
+								B := (P1 <= 0) or (CurPos <= Length (S));
+								if not B then begin
+									B := True;
+									I := CurPos - Length (S);
+									while (I >= 1) and ((Text [I] = CustomStyle.IgnoreChar) or ((CustomStyle.IgnoreChar = '\') and (Copy (Text, I - 2, 3) = '??/'))) do begin
+										B := not B;
+										if Text [I] = CustomStyle.IgnoreChar then
+											Dec (I)
+										else
+											Dec (I, 3);
+									end;
+								end;
+							until B;
+							if S = #13 then
+								Inc (CurPos);
+							if (P1 <= 0) or (CurPos <= Length (S)) or (CurPos > TextLength) then
+								CurPos := TextLength;
+							Inc (CurPos);
+							SectionLength := CurPos - SectionStart;
+							SetSectionType (stText);
+						end;
+						Continue;
+					end else if (SectionType = stCustomStyle) and Assigned (CustomStyle) and CustomStyle.Switchable then begin
+						if CustomStyle.EndText = #13 then
+							L := 2
+						else
+							L := Length (CustomStyle.EndText);
+						Inc (SectionLength, L);
+						Inc (CurPos, L);
+						SetSectionType (stText);
+						Continue;
+					end;
+					if CharIsParenthesis (CurChar) then
+						SetSectionType (stParenthesis)
+					else if CurChar = '.' then begin
+						if ((SectionType = stText) and CharIsNumber (Text [WordStart])) or ((CurPos + 1 <= TextLength) and CharIsNumber (Text [CurPos + 1])) then
+							SetSectionType (stText)
+						else
+							SetSectionType (stSymbol);
+					end else if CurChar in ['+', '-'] then begin
+						if not ((CurPos - 2 >= 1) and CharIsExtNumber (Text [CurPos - 2]) and (CurPos - 1 >= 1) and (Text [CurPos - 1] in ['e', 'E', 'p', 'P'])) then
+							SetSectionType (stSymbol);
+					end else if CharIsSymbol (CurChar) then
+						SetSectionType (stSymbol)
+					else begin
+						SetSectionType (stText);
+						if not CharIsIdentifier (CurChar) then
+							WordStart := CurPos;
+					end;
+				end;
+				Inc (SectionLength);
+				Inc (CurPos);
+			end;
+			Range.REnd := CurPos - 1;
+			if CurPos > TextLength then
+				ProcessSection;
+			LastPRange := SyntaxRangeAtPosWithHint (Range.RStart, LastRange);
+			Dec (SyntaxColoring.FUpdateDebth);
+		end else
+			FreeAllSyntaxRanges;
+	end;
+	{$IFDEF SyntaxDebug}
+		if FindSyntaxHole <> nil then
+			raise ESourceEdit.Create (SSourceEditError);
+	{$ENDIF}
+end;
+
+procedure TSourceEdit.RemoveTrSpFromString(var Str: string;
+	IncludeLastLine: Boolean);
+var
+	I: Integer;
+	OK: Boolean;
+begin
+	if AutoIndentIncrease then begin
+		OK := False;
+		for I := 1 to Length (Str) do
+			if not (Str [I] in [#13, #10, ' ', #9, AutoIndentIncreaseStart, AutoIndentIncreaseEnd]) then begin
+				OK := True;
+				break;
+			end;
+	end else
+		OK := True;
+	if OK then
+		inherited;
+end;
+
+function TSourceEdit.ReplaceSyntaxRanges(NewRange: TSyntaxRange;
+	var StartRange: TSyntaxRange): Boolean;
+var
+	PrevRange: TSyntaxRange;
+begin
+	Result := False;
+	if not Assigned (StartRange) then
+		StartRange := LastSyntaxRange;
+	while Assigned (StartRange) and ((StartRange.RStart > NewRange.RStart) or (StartRange = NewRange)) do
+		StartRange := StartRange.PrevRange;
+	if not Assigned (StartRange) then
+		StartRange := FirstSyntaxRange;
+	while Assigned (StartRange) and ((StartRange.RStart < NewRange.RStart) or (StartRange = NewRange)) do
+		StartRange := StartRange.NextRange;
+	if (not Assigned (StartRange)) and (LastSyntaxRange <> NewRange) then
+		StartRange := LastSyntaxRange;
+	while Assigned (StartRange) and (StartRange <> NewRange) and ((StartRange.RStart <= NewRange.REnd) or (StartRange.REnd <= NewRange.REnd)) do begin
+		Result := StartRange.EqualEndingsWith (NewRange);
+		PrevRange := StartRange;
+		StartRange := StartRange.NextRange;
+		PrevRange.Free;
+	end;
+	{$IFDEF SyntaxDebug}
+		if FindSyntaxOverlap <> nil then
+			raise ESourceEdit.Create (SSourceEditError);
+	{$ENDIF}
+end;
+
+procedure TSourceEdit.SetSplitOnFly(const Value: Boolean);
+begin
+	if FSplitOnFly <> Value then begin
+		FSplitOnFly := Value;
+		ReColor;
+	end;
+end;
+
+procedure TSourceEdit.SetSyntaxColoring(const Value: TSyntaxColoring);
+begin
+	FSyntaxColoring.Assign (Value);
+end;
+
+function TSourceEdit.SyntaxRangeAtPos(RangePos: Integer): TSyntaxRange;
+begin
+	Result := FirstSyntaxRange;
+	while Assigned (Result) and (Result.REnd < RangePos) do
+		Result := Result.NextRange;
+end;
+
+function TSourceEdit.SyntaxRangeAtPosWithHint(RangePos: Integer;
+	Hint: TSyntaxRange): TSyntaxRange;
+begin
+	if Assigned (Hint) then begin
+		Result := Hint;
+		while Assigned (Result) and (Result.REnd >= RangePos) do
+			Result := Result.PrevRange;
+		if not Assigned (Result) then
+			Result := FirstSyntaxRange;
+	end else
+		Result := FirstSyntaxRange;
+	while Assigned (Result) and (Result.REnd < RangePos) do
+		Result := Result.NextRange;
+end;
+
+procedure TSourceEdit.TextChangeNotification(StartPos, OldLength,
+	NewLength: Integer);
+begin
+	inherited;
+	LastPRange := nil;
+	LastCRange := TMCRange.Create (nil);
+	with LastCRange do begin
+		Editor := Self;
+		RStart := StartPos;
+		RLength := NewLength;
+		ReColorRange (LastCRange);
+	end;
+end;
+
+procedure TSourceEdit.TextChangeNotificationAfter;
+begin
+	inherited;
+	if Assigned (LastCRange) then begin
+		while Assigned (LastPRange) do begin
+			if LastPRange.REnd <= LastCRange.REnd then
+				LastPRange.SetNewParenthesisLevel
+			else
+				LastPRange.UpdateParenthesisLevel;
+			LastPRange := LastPRange.NextRange;
+		end;
+		LastCRange.DrawRange;
+		LastCRange.Free;
+		LastCRange := nil;
+	end;
+end;
+
+procedure TSourceEdit.WMKeyDown(var Message: TWMKeyDown);
+var
+	Shift: TShiftState;
+begin
+	if Message.CharCode = vk_Tab then begin
+		Shift := KeyDataToShiftState (Message.KeyData);
+		if ssShift in Shift then
+			ChangeIndent (-1)
+		else if (Selection.RLength > 0) and (Selection.EndRowCol.Row > Selection.StartRowCol.Row) then
+			ChangeIndent (1)
+		else
+			inherited;
+	end else
+		inherited;
+end;
+
+{ TSyntaxColoring }
+
+procedure TSyntaxColoring.Assign(Source: TPersistent);
+begin
+	if Source is TSyntaxColoring then begin
+		BeginUpdate;
+		FEnabled := TSyntaxColoring(Source).Enabled;
+		FSymbolColor := TSyntaxColoring(Source).SymbolColor;
+		FSymbolStyle := TSyntaxColoring(Source).SymbolStyle;
+		FSymbolCustomStyle := TSyntaxColoring(Source).SymbolCustomStyle;
+		FNumberColor := TSyntaxColoring(Source).NumberColor;
+		FNumberStyle := TSyntaxColoring(Source).NumberStyle;
+		FNumberCustomStyle := TSyntaxColoring(Source).NumberCustomStyle;
+		FWordLists.Assign (TSyntaxColoring(Source).WordLists);
+		FCustomStyles.Assign (TSyntaxColoring(Source).CustomStyles);
+		FParenthesisColors.Assign (TSyntaxColoring(Source).ParenthesisColors);
+		FParenthesisStyle := TSyntaxColoring(Source).ParenthesisStyle;
+		FParenthesisCustomStyle := TSyntaxColoring(Source).ParenthesisCustomStyle;
+		EndUpdate;
+	end else if Source is TSyntaxColoringCopy then begin
+		BeginUpdate;
+		FEnabled := TSyntaxColoringCopy(Source).Enabled;
+		FSymbolColor := TSyntaxColoringCopy(Source).SymbolColor;
+		FSymbolStyle := TSyntaxColoringCopy(Source).SymbolStyle;
+		FSymbolCustomStyle := TSyntaxColoringCopy(Source).SymbolCustomStyle;
+		FNumberColor := TSyntaxColoringCopy(Source).NumberColor;
+		FNumberStyle := TSyntaxColoringCopy(Source).NumberStyle;
+		FNumberCustomStyle := TSyntaxColoringCopy(Source).NumberCustomStyle;
+		FWordLists.Assign (TSyntaxColoringCopy(Source).WordLists);
+		FCustomStyles.Assign (TSyntaxColoringCopy(Source).CustomStyles);
+		FParenthesisColors.Assign (TSyntaxColoringCopy(Source).ParenthesisColors);
+		FParenthesisStyle := TSyntaxColoringCopy(Source).ParenthesisStyle;
+		FParenthesisCustomStyle := TSyntaxColoringCopy(Source).ParenthesisCustomStyle;
+		EndUpdate;
+	end else
+		inherited Assign (Source);
+end;
+
+procedure TSyntaxColoring.BeginUpdate;
+begin
+	Inc (FUpdateDebth);
+end;
+
+procedure TSyntaxColoring.ChangeNotification(Sender: TObject);
+begin
+	ColoringChange;
+end;
+
+procedure TSyntaxColoring.ColoringChange;
+var
+	I: Integer;
+begin
+	if FUpdateDebth = 0 then
+		if Assigned (Owner) then
+			if Owner is TSourceEdit then
+				with Owner as TSourceEdit do begin
+					with SymbolFont do begin
+						Assign (Font);
+						Color := SymbolColor;
+						if SymbolCustomStyle then
+							Style := SymbolStyle;
+					end;
+					with NumberFont do begin
+						Assign (Font);
+						Color := NumberColor;
+						if NumberCustomStyle then
+							Style := NumberStyle;
+					end;
+					with ParenthesisFont do begin
+						Assign (Font);
+						Color := GetParenthesisColor (0);
+						if ParenthesisCustomStyle then
+							Style := ParenthesisStyle;
+					end;
+					with WordLists do
+						for I := 0 to Count - 1 do
+							with Items[I].Font do begin
+								Assign (Font);
+								if Items[I].CustomColor then
+									Color := Items[I].Color;
+								if Items[I].CustomStyle then
+									Style := Items[I].Style;
+							end;
+					with CustomStyles do
+						for I := 0 to Count - 1 do
+							with Items[I].Font do begin
+								Assign (Font);
+								if Items[I].CustomColor then
+									Color := Items[I].Color;
+								if Items[I].CustomStyle then
+									Style := Items[I].Style;
+							end;
+					ReColor;
+				end;
+end;
+
+constructor TSyntaxColoring.Create(AOwner: TPersistent);
+begin
+	inherited;
+	SymbolFont := TFont.Create;
+	NumberFont := TFont.Create;
+	ParenthesisFont := TFont.Create;
+	FWordLists := TWordLists.Create (Self);
+	FCustomStyles := TCustomStyles.Create (Self);
+	FParenthesisColors := TStringList.Create;
+	FParenthesisColors.Duplicates := dupAccept;
+	FParenthesisColors.Add ('$000000');
+	FParenthesisColors.OnChange := ChangeNotification;
+	FNumberColor := clGreen;
+	FSymbolColor := clOlive;
+	FEnabled := True;
+end;
+
+destructor TSyntaxColoring.Destroy;
+begin
+	FParenthesisColors.Free;
+	FCustomStyles.Free;
+	FWordLists.Free;
+	NumberFont.Free;
+	SymbolFont.Free;
+	ParenthesisFont.Free;
+	inherited;
+end;
+
+procedure TSyntaxColoring.EndUpdate;
+begin
+	Dec (FUpdateDebth);
+	if FUpdateDebth = 0 then
+		ColoringChange;
+end;
+
+function TSyntaxColoring.GetParenthesisColor(Index: Integer): TColor;
+begin
+	with ParenthesisColors do
+		if (Count <= 0) or (Index < 0) then
+			Result := clWindowText
+		else
+			try
+				Result := StrToInt (Strings [Index mod Count]);
+			except
+				Result := clWindowText;
+			end;
+end;
+
+procedure TSyntaxColoring.SetCustomStyles(const Value: TCustomStyles);
+begin
+	FCustomStyles.Assign (Value);
+	ColoringChange;
+end;
+
+procedure TSyntaxColoring.SetEnabled(const Value: Boolean);
+begin
+	if FEnabled <> Value then begin
+		FEnabled := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetNumberColor(const Value: TColor);
+begin
+	if FNumberColor <> Value then begin
+		FNumberColor := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetNumberCustomStyle(const Value: Boolean);
+begin
+	if FNumberCustomStyle <> Value then begin
+		FNumberCustomStyle := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetNumberStyle(const Value: TFontStyles);
+begin
+	if FNumberStyle <> Value then begin
+		FNumberStyle := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetParenthesisColors(const Value: TStringList);
+begin
+	FParenthesisColors.Assign (Value);
+end;
+
+procedure TSyntaxColoring.SetParenthesisCustomStyle(const Value: Boolean);
+begin
+	if FParenthesisCustomStyle <> Value then begin
+		FParenthesisCustomStyle := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetParenthesisStyle(const Value: TFontStyles);
+begin
+	if FParenthesisStyle <> Value then begin
+		FParenthesisStyle := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetSymbolColor(const Value: TColor);
+begin
+	if FSymbolColor <> Value then begin
+		FSymbolColor := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetSymbolCustomStyle(const Value: Boolean);
+begin
+	if FSymbolCustomStyle <> Value then begin
+		FSymbolCustomStyle := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetSymbolStyle(const Value: TFontStyles);
+begin
+	if FSymbolStyle <> Value then begin
+		FSymbolStyle := Value;
+		ColoringChange;
+	end;
+end;
+
+procedure TSyntaxColoring.SetWordLists(const Value: TWordLists);
+begin
+	FWordLists.Assign (Value);
+	ColoringChange;
+end;
+
+{ TWordLists }
+
+function TWordLists.Add: TWordList;
+begin
+	Result := TWordList (inherited Add);
+end;
+
+constructor TWordLists.Create(AColoring: TSyntaxColoring);
+begin
+	inherited Create (TWordList);
+	FColoring := AColoring;
+end;
+
+function TWordLists.FindList(const S: string): TWordList;
+var
+	I: Integer;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do
+		if Items[I].WordInList (S) then begin
+			Result := Items [I];
+			Break;
+		end;
+end;
+
+function TWordLists.GetItem(Index: Integer): TWordList;
+begin
+	Result := TWordList (inherited GetItem (Index));
+end;
+
+function TWordLists.GetOwner: TPersistent;
+begin
+	Result := FColoring;
+end;
+
+procedure TWordLists.SetItem(Index: Integer; Value: TWordList);
+begin
+	inherited SetItem (Index, Value);
+end;
+
+procedure TWordLists.Update(Item: TCollectionItem);
+begin
+	if Assigned (Item) then
+		TWordList(Item).ListChange
+	else
+		if Assigned (FColoring) then
+			FColoring.ColoringChange;
+end;
+
+{ TWordList }
+
+procedure TWordList.Assign(Source: TPersistent);
+begin
+	if Source is TWordList then begin
+		Caption := TWordList(Source).Caption;
+		FCustomColor := TWordList(Source).CustomColor;
+		FColor := TWordList(Source).Color;
+		FCustomStyle := TWordList(Source).CustomStyle;
+		FStyle := TWordList(Source).Style;
+		FCaseSensitive := TWordList(Source).CaseSensitive;
+		FWords.Assign (TWordList(Source).Words);
+		ListChange;
+	end else
+		inherited Assign (Source);
+end;
+
+procedure TWordList.ChangeNotification(Sender: TObject);
+begin
+	ListChange;
+end;
+
+constructor TWordList.Create(Collection: TCollection);
+begin
+	inherited;
+	Font := TFont.Create;
+	FWords := TStringList.Create;
+	FWords.Sorted := True;
+	FWords.Duplicates := dupAccept;
+	FWords.OnChange := ChangeNotification;
+	FColor := clBlue;
+	FCustomColor := True;
+	FCaseSensitive := True;
+end;
+
+destructor TWordList.Destroy;
+begin
+	FWords.Free;
+	Font.Free;
+	inherited;
+end;
+
+function TWordList.GetDisplayName: string;
+begin
+	if FDisplayName = '' then
+		Result := inherited GetDisplayName
+	else
+		Result := FDisplayName;
+end;
+
+procedure TWordList.ListChange;
+begin
+	if Assigned (Collection) then
+		with TWordLists (Collection) do
+			if Assigned (FColoring) then
+				FColoring.ColoringChange;
+end;
+
+procedure TWordList.SetCaseSensitive(const Value: Boolean);
+begin
+	if FCaseSensitive <> Value then begin
+		FCaseSensitive := Value;
+		ListChange;
+	end;
+end;
+
+procedure TWordList.SetColor(const Value: TColor);
+begin
+	if FColor <> Value then begin
+		FColor := Value;
+		ListChange;
+	end;
+end;
+
+procedure TWordList.SetCustomColor(const Value: Boolean);
+begin
+	if FCustomColor <> Value then begin
+		FCustomColor := Value;
+		ListChange;
+	end;
+end;
+
+procedure TWordList.SetCustomStyle(const Value: Boolean);
+begin
+	if FCustomStyle <> Value then begin
+		FCustomStyle := Value;
+		ListChange;
+	end;
+end;
+
+procedure TWordList.SetDisplayName(const Value: string);
+begin
+	if FDisplayName <> Value then begin
+		FDisplayName := Value;
+		inherited;
+	end;
+end;
+
+procedure TWordList.SetStyle(const Value: TFontStyles);
+begin
+	if FStyle <> Value then begin
+		FStyle := Value;
+		ListChange;
+	end;
+end;
+
+procedure TWordList.SetWords(const Value: TStringList);
+begin
+	FWords.Assign (Value);
+	ListChange;
+end;
+
+function TWordList.WordInList(S: string): Boolean;
+var
+	I: Integer;
+begin
+	if CaseSensitive then
+		Result := Words.Find (S, I) and (I >= 0) and (I < Words.Count) and (S = Words.Strings [I])
+	else
+		Result := Words.Find (S, I) or ((I >= 0) and (I < Words.Count) and (UpperCase (S) = UpperCase (Words.Strings [I])));
+end;
+
+{ TCustomStyles }
+
+function TCustomStyles.Add: TCustomStyle;
+begin
+	Result := TCustomStyle (inherited Add);
+end;
+
+constructor TCustomStyles.Create(AColoring: TSyntaxColoring);
+begin
+	inherited Create (TCustomStyle);
+	FColoring := AColoring;
+end;
+
+function TCustomStyles.FindStyle(const S: string): TCustomStyle;
+var
+	I: Integer;
+begin
+	Result := nil;
+	if S <> '' then
+		for I := 0 to Count - 1 do
+			if Items[I].BeginText = Copy (S, 1, Length (Items[I].BeginText)) then begin
+				Result := Items [I];
+				Break;
+			end;
+end;
+
+function TCustomStyles.GetItem(Index: Integer): TCustomStyle;
+begin
+	Result := TCustomStyle (inherited GetItem (Index));
+end;
+
+function TCustomStyles.GetOwner: TPersistent;
+begin
+	Result := FColoring;
+end;
+
+procedure TCustomStyles.SetItem(Index: Integer; Value: TCustomStyle);
+begin
+	inherited SetItem (Index, Value);
+end;
+
+procedure TCustomStyles.Update(Item: TCollectionItem);
+begin
+	if Assigned (FColoring) then
+		FColoring.ColoringChange;
+end;
+
+{ TCustomStyle }
+
+procedure TCustomStyle.Assign(Source: TPersistent);
+begin
+	if Source is TCustomStyle then begin
+		Caption := TCustomStyle(Source).Caption;
+		FCustomColor := TCustomStyle(Source).CustomColor;
+		FColor := TCustomStyle(Source).Color;
+		FCustomStyle := TCustomStyle(Source).CustomStyle;
+		FStyle := TCustomStyle(Source).Style;
+		FBeginText := TCustomStyle(Source).BeginText;
+		FEndText := TCustomStyle(Source).EndText;
+		FIgnoreChar := TCustomStyle(Source).IgnoreChar;
+		FSwitchable := TCustomStyle(Source).Switchable;
+		FLineStartOnly := TCustomStyle(Source).LineStartOnly;
+		FIgnoreLeadingBlanks := TCustomStyle(Source).IgnoreLeadingBlanks;
+		StyleChange;
+	end else
+		inherited Assign (Source);
+end;
+
+constructor TCustomStyle.Create(Collection: TCollection);
+begin
+	inherited;
+	Font := TFont.Create;
+	FColor := clMaroon;
+	FCustomColor := True;
+end;
+
+destructor TCustomStyle.Destroy;
+begin
+	Font.Free;
+	inherited;
+end;
+
+function TCustomStyle.GetDisplayName: string;
+begin
+	if FDisplayName = '' then
+		Result := inherited GetDisplayName
+	else
+		Result := FDisplayName;
+end;
+
+procedure TCustomStyle.SetBeginText(Value: string);
+begin
+	if Value = '#13' then
+		Value := #13;
+	if FBeginText <> Value then begin
+		FBeginText := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetColor(const Value: TColor);
+begin
+	if FColor <> Value then begin
+		FColor := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetCustomColor(const Value: Boolean);
+begin
+	if FCustomColor <> Value then begin
+		FCustomColor := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetCustomStyle(const Value: Boolean);
+begin
+	if FCustomStyle <> Value then begin
+		FCustomStyle := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetDisplayName(const Value: string);
+begin
+	FDisplayName := Value;
+end;
+
+procedure TCustomStyle.SetEndText(Value: string);
+begin
+	if Value = '#13' then
+		Value := #13;
+	if FEndText <> Value then begin
+		FEndText := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetIgnoreChar(const Value: TIgnoreChar);
+begin
+	if FIgnoreChar <> Value then begin
+		FIgnoreChar := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetIgnoreLeadingBlanks(const Value: Boolean);
+begin
+	if FIgnoreLeadingBlanks <> Value then begin
+		FIgnoreLeadingBlanks := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetLineStartOnly(const Value: Boolean);
+begin
+	if FLineStartOnly <> Value then begin
+		FLineStartOnly := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetStyle(const Value: TFontStyles);
+begin
+	if FStyle <> Value then begin
+		FStyle := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.SetSwitchable(const Value: Boolean);
+begin
+	if FSwitchable <> Value then begin
+		FSwitchable := Value;
+		StyleChange;
+	end;
+end;
+
+procedure TCustomStyle.StyleChange;
+begin
+	if Assigned (Collection) then
+		with TCustomStyles (Collection) do
+			if Assigned (FColoring) then
+				FColoring.ColoringChange;
+end;
+
+{ TSyntaxColoringCopy }
+
+procedure TSyntaxColoringCopy.Assign(Source: TPersistent);
+begin
+	if Source is TSyntaxColoring then begin
+		FEnabled := TSyntaxColoring(Source).Enabled;
+		FSymbolColor := TSyntaxColoring(Source).SymbolColor;
+		FSymbolStyle := TSyntaxColoring(Source).SymbolStyle;
+		FSymbolCustomStyle := TSyntaxColoring(Source).SymbolCustomStyle;
+		FNumberColor := TSyntaxColoring(Source).NumberColor;
+		FNumberStyle := TSyntaxColoring(Source).NumberStyle;
+		FNumberCustomStyle := TSyntaxColoring(Source).NumberCustomStyle;
+		FWordLists.Assign (TSyntaxColoring(Source).WordLists);
+		FCustomStyles.Assign (TSyntaxColoring(Source).CustomStyles);
+		FParenthesisColors.Assign (TSyntaxColoring(Source).ParenthesisColors);
+		FParenthesisStyle := TSyntaxColoring(Source).ParenthesisStyle;
+		FParenthesisCustomStyle := TSyntaxColoring(Source).ParenthesisCustomStyle;
+	end else
+		inherited Assign (Source);
+end;
+
+constructor TSyntaxColoringCopy.Create(AOwner: TComponent);
+begin
+	inherited;
+	FWordLists := TWordLists.Create (nil);
+	FCustomStyles := TCustomStyles.Create (nil);
+	FParenthesisColors := TStringList.Create;
+	FParenthesisColors.Duplicates := dupAccept;
+	FParenthesisColors.Add ('$000000');
+	FNumberColor := clGreen;
+	FSymbolColor := clOlive;
+	FEnabled := True;
+end;
+
+destructor TSyntaxColoringCopy.Destroy;
+begin
+	FParenthesisColors.Free;
+	FCustomStyles.Free;
+	FWordLists.Free;
+	inherited;
+end;
+
+procedure TSyntaxColoringCopy.SetCustomStyles(const Value: TCustomStyles);
+begin
+	FCustomStyles.Assign (Value);
+end;
+
+procedure TSyntaxColoringCopy.SetParenthesisColors(
+	const Value: TStringList);
+begin
+	FParenthesisColors.Assign (Value);
+end;
+
+procedure TSyntaxColoringCopy.SetWordLists(const Value: TWordLists);
+begin
+	FWordLists.Assign (Value);
+end;
+
+{ TSyntaxRange }
+
+destructor TSyntaxRange.Destroy;
+begin
+	if Assigned (Collection) and (not (Collection as TMCRanges).FDestroying) then begin
+		if Assigned (Editor) and ((Editor as TSourceEdit).SyntaxStartRange = Self) then
+			(Editor as TSourceEdit).SyntaxStartRange := nil;
+		if Assigned (PrevRange) then
+			PrevRange.NextRange := NextRange
+		else if Assigned (Editor) then
+			(Editor as TSourceEdit).FirstSyntaxRange := NextRange;
+		if Assigned (NextRange) then
+			NextRange.PrevRange := PrevRange
+		else if Assigned (Editor) then
+			(Editor as TSourceEdit).LastSyntaxRange := PrevRange;
+	end;
+	inherited;
+end;
+
+class function TSyntaxRange.EqualEndings(Range1,
+	Range2: TSyntaxRange): Boolean;
+begin
+	Result := Assigned (Range1) and Assigned (Range2) and Range1.EqualEndingsWith (Range2);
+end;
+
+function TSyntaxRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := REnd = Range.REnd;
+end;
+
+function TSyntaxRange.GetColor: TColor;
+begin
+	if Assigned (Editor) then
+		Result := Editor.Color
+	else
+		Result := clWindow;
+end;
+
+function TSyntaxRange.GetNextParenthesisLevel: Integer;
+begin
+	Result := ParenthesisLevel;
+end;
+
+function TSyntaxRange.InsertAfter(RangeClass: TSyntaxRangeClass):
+	TSyntaxRange;
+begin
+	Result := InsertRangeBefore (NextRange, RangeClass, Editor as TSourceEdit);
+end;
+
+function TSyntaxRange.InsertBefore(RangeClass: TSyntaxRangeClass):
+	TSyntaxRange;
+begin
+	Result := InsertRangeBefore (Self, RangeClass, Editor as TSourceEdit);
+end;
+
+class function TSyntaxRange.InsertRangeBefore(Range: TSyntaxRange;
+	RangeClass: TSyntaxRangeClass; Editor: TSourceEdit): TSyntaxRange;
+	// If Range is nil, new item is inserted at the end.
+begin
+	if Assigned (Editor) then begin
+		Result := RangeClass.Create (Editor.TrackedRanges);
+		Result.OnOverwrite := Editor.OverwriteRange;
+		if Assigned (Range) then
+			Result.PrevRange := Range.PrevRange
+		else
+			Result.PrevRange := Editor.LastSyntaxRange;
+		Result.NextRange := Range;
+		if Assigned (Range) then begin
+			if Assigned (Range.PrevRange) then
+				Range.PrevRange.NextRange := Result
+			else
+				Editor.FirstSyntaxRange := Result;
+		end else begin
+			if not Assigned (Editor.FirstSyntaxRange) then
+				Editor.FirstSyntaxRange := Result;
+			if Assigned (Editor.LastSyntaxRange) then
+				Editor.LastSyntaxRange.NextRange := Result;
+			Editor.LastSyntaxRange := Result;
+		end;
+		if Assigned (Range) then
+			Range.PrevRange := Result;
+	end else
+		raise ESourceEdit.Create (SSourceEditError);
+end;
+
+class function TSyntaxRange.NewRangeInsertedAfter(Range: TSyntaxRange;
+	Editor: TSourceEdit): TSyntaxRange;
+begin
+	if Assigned (Range) then
+		Result := InsertRangeBefore (Range.NextRange, Self, Editor)
+	else
+		Result := nil;
+end;
+
+class function TSyntaxRange.NewRangeInsertedBefore(Range: TSyntaxRange;
+	Editor: TSourceEdit): TSyntaxRange;
+begin
+	Result := InsertRangeBefore (Range, Self, Editor);
+end;
+
+function TSyntaxRange.ReplaceSyntaxRanges(var StartRange: TSyntaxRange):
+	Boolean;
+begin
+	if Assigned (Editor) and (Editor is TSourceEdit) then
+		Result := TSourceEdit(Editor).ReplaceSyntaxRanges (Self, StartRange)
+	else
+		Result := False;
+end;
+
+procedure TSyntaxRange.SetNewParenthesisLevel;
+begin
+	if Assigned (PrevRange) then
+		ParenthesisLevel := PrevRange.NextParenthesisLevel
+	else
+		ParenthesisLevel := 0;
+end;
+
+procedure TSyntaxRange.UpdateParenthesisLevel;
+begin
+	SetNewParenthesisLevel;
+end;
+
+{ TNormalTextRange }
+
+function TNormalTextRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TNormalTextRange) and (inherited EqualEndingsWith (Range));
+end;
+
+function TNormalTextRange.GetFont: TFont;
+begin
+	if Assigned (Editor) then
+		Result := Editor.Font
+	else
+		Result := nil;
+end;
+
+{ TCustomStyleRange }
+
+function TCustomStyleRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TCustomStyleRange) and (inherited EqualEndingsWith (Range)) and (Style = TCustomStyleRange(Range).Style);
+end;
+
+function TCustomStyleRange.GetFont: TFont;
+begin
+	if Assigned (Style) then
+		Result := Style.Font
+	else
+		Result := nil;
+end;
+
+{ TWordListRange }
+
+function TWordListRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TWordListRange) and (inherited EqualEndingsWith (Range)) and (WordList = TWordListRange(Range).WordList);
+end;
+
+function TWordListRange.GetFont: TFont;
+begin
+	Result := WordList.Font;
+end;
+
+{ TSymbolRange }
+
+function TSymbolRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TSymbolRange) and (inherited EqualEndingsWith (Range)) and (Symbol = TSymbolRange(Range).Symbol);
+end;
+
+function TSymbolRange.GetFont: TFont;
+begin
+	if Assigned (Editor) then begin
+		with Editor as TSourceEdit do
+			if SyntaxColoring.Enabled then
+				Result := SyntaxColoring.SymbolFont
+			else
+				Result := Font;
+	end else
+		Result := nil;
+end;
+
+{ TNumberRange }
+
+function TNumberRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TNumberRange) and (inherited EqualEndingsWith (Range)) and (Number = TNumberRange(Range).Number);
+end;
+
+function TNumberRange.GetFont: TFont;
+begin
+	if Assigned (Editor) then begin
+		with Editor as TSourceEdit do
+			if SyntaxColoring.Enabled then
+				Result := SyntaxColoring.NumberFont
+			else
+				Result := Font;
+	end else
+		Result := nil;
+end;
+
+{ TParenthesisRange }
+
+function TParenthesisRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TParenthesisRange) and (inherited EqualEndingsWith (Range)) and (Style = TParenthesisRange(Range).Style);
+end;
+
+function TParenthesisRange.GetFont: TFont;
+begin
+	if Assigned (Editor) then begin
+		with Editor as TSourceEdit do
+			if SyntaxColoring.Enabled then begin
+				Result := SyntaxColoring.ParenthesisFont;
+				Result.Color := SyntaxColoring.GetParenthesisColor (ParenthesisLevel - 1);
+			end else
+				Result := Font;
+	end else
+		Result := nil;
+end;
+
+function TParenthesisRange.GetNextParenthesisLevel: Integer;
+begin
+	if Style = psOpening then
+		Result := inherited GetNextParenthesisLevel
+	else
+		Result := inherited GetNextParenthesisLevel - 1;
+end;
+
+procedure TParenthesisRange.SetNewParenthesisLevel;
+begin
+	if Style = psClosing then
+		inherited SetNewParenthesisLevel
+	else
+		if Assigned (PrevRange) then
+			ParenthesisLevel := PrevRange.NextParenthesisLevel + 1
+		else
+			ParenthesisLevel := 1;
+end;
+
+procedure TParenthesisRange.UpdateParenthesisLevel;
+var
+	Lev: Integer;
+begin
+	Lev := ParenthesisLevel;
+	inherited;
+	if Lev <> ParenthesisLevel then
+		DrawRange;
+end;
+
+{ TCustomTextRange }
+
+function TCustomTextRange.EqualEndingsWith(Range: TSyntaxRange): Boolean;
+begin
+	Result := (Range is TCustomTextRange) and (inherited EqualEndingsWith (Range));
+end;
+
+function TCustomTextRange.GetFont: TFont;
+begin
+	if Assigned (Editor) then
+		Result := Editor.Font
+	else
+		Result := nil;
+end;
+
+end.

+ 69 - 0
tigcc/components/URLLabelUnit.pas

@@ -0,0 +1,69 @@
+unit URLLabelUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls;
+
+type
+	TShowWindowStyle = (swHide, swShowNormal, swShowMinimized, swShowMaximized, swMaximize, swShowNoActivate, swShow, swMinimize, swShowMinNoActivate, swShowNA, swRestore, swShowDefault);
+
+	TURLLabel = class(TStaticText)
+	private
+		FURL: string;
+    FShowWindow: TShowWindowStyle;
+	protected
+		procedure CreateWnd; override;
+	public
+		constructor Create(AOwner: TComponent); override;
+		procedure Click; override;
+	published
+		property URL: string read FURL write FURL;
+		property ShowWindow: TShowWindowStyle read FShowWindow write FShowWindow;
+	end;
+
+procedure Register;
+
+implementation
+
+uses
+	ShellAPI;
+
+procedure Register;
+begin
+	RegisterComponents('User', [TURLLabel]);
+end;
+
+{ TURLLabel }
+
+procedure TURLLabel.Click;
+begin
+	inherited;
+	if Length (URL) > 0 then
+		ShellExecute (0, nil, PChar (URL), nil, nil, Integer (ShowWindow));
+end;
+
+constructor TURLLabel.Create(AOwner: TComponent);
+begin
+	inherited;
+	Font.Color := clHighlight;
+	Font.Style := Font.Style + [fsUnderline];
+	FURL := '';
+	FShowWindow := swShow;
+end;
+
+procedure TURLLabel.CreateWnd;
+var
+	NewCursor: HCursor;
+begin
+	inherited;
+	if HandleAllocated and not (csDesigning in ComponentState) then begin
+		NewCursor := LoadCursor (0, idc_Hand);
+		if NewCursor = 0 then
+			NewCursor := Screen.Cursors [crHandPoint];
+		SetClassLong (Handle, gcl_HCursor, NewCursor);
+	end;
+end;
+
+end.

+ 180 - 0
tigcc/gcc/ChangeLog-gas.txt

@@ -0,0 +1,180 @@
+Changelog of the TIGCC-local changes to Binutils (2.14 branch):
+
+2004-09-20  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/read.c (emit_expr): Mark relocs for constants unoptimizable.
+	* gas/write.h (struct fix): Add fx_unoptimizable field.
+	* gas/write.c (fix_new_internal): Initialize it.
+	* include/coff/internal.h (R_UNOPTIMIZABLE): New reloc flag.
+	* gas/config/tc-m68k.c (tc_coff_fix2rtype): Handle unoptimizable relocs.
+	  (md_assemble): Mark destination operand relocs unoptimizable.
+
+2004-09-05  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/as.h (segment_name): Change to function to allow arbitrary number of sections.
+	* gas/subsegs.c (seg_name, segment_name): Likewise.
+	* gas/symbols.h (SEGMENT_TO_SYMBOL_TYPE): Likewise.
+	* gas/config/obj-coff.c (seg_N_TYPE, SEGMENT_TO_SYMBOL_TYPE): Likewise.
+	  (seg_info_off_by_4, SEG_INFO_FROM_SECTION_NUMBER): Likewise.
+	* gas/config/obj-coff.h (C_REGISTER_SECTION): Redefine to N_SEGMENTS+10.
+	* gas/as.h (SEG_NORMAL): Redefine to use SEG_LAST.
+	  (N_SEGMENTS, SEG_LIST, SEG_LAST): Bump segment limit from 120 to 1024.
+
+2004-08-07  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/tc-m68k.c (md_apply_fix3): Don't add/subtract the value of a common symbol,
+	                                        it is a size, not a position.
+
+2004-07-25  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/obj-coff.h (S_FORCE_RELOC): Force relocs for symbols in mergeable sections.
+	* gas/config/obj-coff.c (yank_symbols): Clear the SF_LOCAL flag if the symbol is in a
+                                                mergeable section.
+
+2004-07-24  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* include/coff/internal.h (STYP_MERGEABLE, STYP_UNALIGNED): New TIGCC section flags.
+	* gas/config/obj-coff.c (obj_coff_section): Use them ("m" and "u" codes).
+	* gas/config/obj-coff.h (S_IS_LOCAL): Always output local symbols in mergeable sections.
+
+2004-07-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/obj-coff.h (S_FORCE_RELOC): Don't force relocs for absolute symbols if
+	                                         !flag_all_relocs.
+	* gas/expr.c (expr): Don't optimize address differences if flag_all_relocs.
+	* gas/symbols.c (resolve_symbol_value): Error out on operations other than + or - on an
+	                                        address or address difference if flag_all_relocs.
+
+2004-06-25  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/as.h (N_SEGMENTS, SEG_NORMAL, SEG_LIST, SEG_LAST): Bump segment limit from 40 to 120.
+	* gas/subsegs.c (MANY_SEGMENTS): Increase segment limit.
+	* gas/config/obj-coff.c (seg_N_TYPE, seg_info_off_by_4): Likewise.
+	* gas/config/obj-coff.h (C_REGISTER_SECTION): Likewise.
+
+	* gas/config/obj-coff.c (obj_coff_add_segment): Use the full name, not the truncated name,
+	                                                for merging of identically-named sections.
+
+2003-09-09  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/tc-m68k.c (md_estimate_size_before_relax): Only create the symbol in the next
+	                                                        frag for conditional jumps.
+            Also handle conditional jumps to variables in the same segment.
+
+2003-09-08  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/tc-m68k.c (md_convert_frag_1): Comment Sebastian Reichelt's change.
+	  (md_estimate_size_before_relax): Likewise.
+
+2003-09-08  Sebastian Reichelt  <Sebastian@tigcc.ticalc.org>
+
+	* gas/config/tc-m68k.c (flag_short_jumps): New variable.
+	  (md_estimate_size_before_relax): Use it instead of flag_short_refs for jump shortening.
+	                                   Handle flag_short_refs in the ABSTOPCREL case.
+	  (md_longopts): Add --short-jumps (OPTION_SHORT_JUMPS).
+	  (md_parse_option): Handle --short-jumps, make -l imply it.
+	  (md_show_usage): Add --short-jumps.
+
+	* gas/frags.h: (struct frag): Add fr_start_symbol member.
+	* gas/config/tc-m68k.c (md_convert_frag_1): Create the jbCC PC-relative reloc using it
+	                                       (in the next frag), not the section symbol of sec.
+	                                       Revert 2003-09-02 addition of segT sec parameter.
+	  (md_convert_frag): Revert 2003-09-02 change ("Pass sec parameter on to
+	                     md_convert_frag_1").
+	  (md_estimate_size_before_relax): For LONG references, create a symbol in the next frag.
+
+2003-09-02  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/tc-m68k.c (m68k_ip): Create PC-relative reloc for the branch in a jbCC.
+	  (md_convert_frag_1): Likewise. Add segT sec parameter.
+	  (md_convert_frag): Pass sec parameter on to md_convert_frag_1.
+
+2003-09-01  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* opcodes/m68k-opc.c (m68k_opcodes): Move 2002-05-12 exgl (exg.l) alias for exg...
+	  (m68k_aliases): ... here. Add abcdb (abcd.b) alias for abcd.
+	* gas/listing.c (listing_listing): Add 1 to the width for the terminating '\0' character.
+
+2003-08-07  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/config/obj-coff.c (do_relocs_for): Do convert references to local symbols we aren't
+                                            going to output into references to the section symbol.
+
+2003-07-17  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/expr.c (expr): Add optimization of subtraction of .set symbols.
+	* gas/config/obj-coff.c (fixup_segment): Zero out add_symbolP only if !TC_FORCE_RELOCATION.
+	  (c_dot_file_symbol [!BFD_ASSEMBLER]): If flag_all_relocs, xdef __ld_all_relocs.
+	* gas/config/tc-m68k.c (md_apply_fix3): Fix offset computation (don't subtract
+	      fixP->fx_frag->fr_address, subtract subtrahend twice instead to compensate for later
+	      incorrect computations in obj-coff.c).
+	    Disable: "Fix up subtraction of the dot symbol by changing the reloc to PC-relative."
+	             (TIGCC 20030716), because it is unnecessary and probably wrong.
+
+2003-07-16  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gas/as.c (show_usage, parse_args): Add --all-relocs switch.
+	* gas/as.h (flag_all_relocs): New variable.
+	* gas/config/obj-coff.h (S_IS_LOCAL): Output even internal symbols when flag_keep_locals.
+	  (S_FORCE_RELOC): Never reduce or eliminate relocs in all-relocs mode.
+	* gas/config/obj-coff.c (fixup_segment): Take TC_FORCE_RELOCATION_SUB_LOCAL and
+	                                         UNDEFINED_DIFFERENCE_OK into account.
+	                                         Reuse fx_im_disp to turn off range checking on the
+	                                         68k.
+	  (do_relocs_for): Don't convert references to references to the section symbol.
+	* gas/config/tc-m68k.h (UNDEFINED_DIFFERENCE_OK): Define.
+	  (TC_FORCE_RELOCATION, TC_FORCE_RELOCATION_ABS, TC_FORCE_RELOCATION_LOCAL,
+	   TC_FORCE_RELOCATION_SUB_SAME, TC_FORCE_RELOCATION_SUB_LOCAL, TC_FORCE_RELOCATION):
+	    Define. Force relocs in all-relocs mode.
+	* gas/config/tc-m68k.c (tc_coff_fix2rtype): Handle word and byte negative relocs.
+	  (md_apply_fix3): We aren't done when we still have something to subtract.
+	                   Split address differences into its components.
+	                   Fix up subtraction of the dot symbol by changing the reloc to
+	                   PC-relative.
+	                   Reuse fx_im_disp to turn off range checking.
+	* gas/write.c (adjust_reloc_syms): Only convert relocs to section symbol relocs if we 
+	                                   aren't going to output the symbol they refer to.
+	* include/coff/internal.h (R_RELWORD_NEG, R_RELBYTE_NEG): Define as TIGCC extensions.
+
+2003-07-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Don't pad sections. ld-tigcc aligns sections independently of their size:
+	  gas/config/obj-coff.c (SUB_SEGMENT_ALIGN for write_object_file): Set to 0, not 1.
+	  gas/write.c (subsegs_finish): Always skip alignment code.
+
+2003-07-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge TIGCC patchset:
+
+	  2003-01-06  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	  * gas/config/obj-coff.c (coff_frob_section): Don't pad sections. ld-tigcc aligns
+	                                               sections independently of their size.
+
+	  2002-05-28  Sebastian Reichelt  <Sebastian@tigcc.ticalc.org>
+
+	  * opcodes/configure.in: Use m68k-dis.c as a "unique file" rather than z8k-dis.c. We
+	                          don't distribute the latter.
+	  * opcodes/configure: Likewise.
+
+	  2002-05-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	  * opcodes/m68k-opc.c (m68k_opcodes): Add exgl (exg.l) alias for exg.
+
+	  2002-01-20  Sebastian Reichelt  <Sebastian@tigcc.ticalc.org>
+
+	  * opcodes/m68k-opc.c (m68k_opcodes): Optimization: Add clr.l %dn as an alias for moveq.
+
+	  2002-01-10  Stephan Effelsberg  <b012414@dvz.fh-koeln.de>
+
+	  * opcodes/m68k-opc.c (m68k_opcodes): Fix cmpi operand constraints when aliased as cmp. 
+	                                       (Don't allow PC-relative or indexed PC-relative
+                                               second operand.)
+
+	  2001-09-01  Sebastian Reichelt  <Sebastian@tigcc.ticalc.org>
+
+	  * bfd/config.bfd: Remove targ_selvecs for m68k-*-*-coff*.
+
+2003-07-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Import Binutils 2.14 release.

+ 818 - 0
tigcc/gcc/ChangeLog.txt

@@ -0,0 +1,818 @@
+Changelog of the TIGCC-local changes to GCC (3.3 branch):
+
+2004-09-25 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Backport from mainline:
+	  2004-06-02  Andreas Schwab  <schwab@suse.de>
+
+		* config/m68k/m68k.c (output_andsi3): Fix detection of narrowable
+		operation for 64 bit hosts.
+
+	* Apply proposed patch from http://gcc.gnu.org/ml/gcc-patches/2003-12/msg00717.html:
+	  2003-12-07  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+	        PR optimization/12085
+	        * tree-inline.c (expand_call_inline): Do not inline functions at
+		calling points where they are viewed with too different a prototype
+		than the actual one.
+
+	* ifcvt.c (noce_operand_ok): Don't if-convert global register variables.
+	  (dead_or_predicable): Likewise.
+
+2004-08-08 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* varasm.c (output_addressed_constants): Address differences are not reloc-free for TIGCC.
+	  (default_select_section): Don't put compound literals in mergeable sections if they
+	                            contain relocations.
+
+	* config/m68k/m68k.c (print_operand): Add -__relation(%an) after a MEM(CONST) if
+	                                      reg-relative.
+	* final.c (output_asm_insn): Likewise.
+	* config/m68k/m68k.h (EXTRA_CONSTRAINT): Disable 'T' if reg-relative.
+	  (LEGITIMATE_CONSTANT_P): Disallow pcrel_address (#label or #label+const) if reg-relative.
+	* config/m68k/m68k.md (unnamed pattern for expanded movesi): Also enable the TARGET_PCREL
+	    lea/pea pattern if TARGET_REG_RELATIVE.
+
+	* config/m68k/m68k.md (cmphi, cmpqi, 2 unnamed patterns related to them): Accept only
+	    nonimmediate_operand, not nonimmediate_src_operand. (Fixes invalid ASM with -mpcrel.)
+
+2004-08-05 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.3-tigcc-6 released as part of TIGCC 0.95 Beta 15.
+
+2004-07-28 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* c-format.c (check_format_types): Warn if someone passes an integer where a
+	                                   floating-point constant is expected.
+
+2004-07-27 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* varasm.c (default_select_section): Put compound literals (if
+	    flag_global_compound_literals) and complex literals in mergeable sections.
+
+	* flags.h (flag_merge_constant_pools): New flag.
+	* toplev.c (flag_merge_constant_pools): Likewise. Default to 1.
+	  (f_options): Add -fmerge-constant-pools.
+	* varasm.c (output_constant_pool): Create new mergeable section for constant pool if
+	                                   (flag_merge_constants && flag_merge_constant_pools).
+
+2004-07-26 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.3-tigcc-5 released as part of TIGCC 0.95 Beta 14.
+
+2004-07-25 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k.c (m68k_coff_asm_named_section): Handle mergeable and unaligned flag.
+	* varasm.c (enum section_category): Move declaration up.
+	  (categorize_decl_for_section): Move prototype up.
+	  (mergeable_string_section): Implement string merging for TIGCC-extended COFF.
+	  (mergeable_constant_section): Implement constant merging for TIGCC-extended COFF.
+	  (default_select_section): Add support for mergeable sections.
+	  (default_section_type_flags_1): Likewise.
+
+2004-07-20 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.3-tigcc-4 released as part of TIGCC 0.95 Beta 13.
+
+2004-07-19 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* stmt.c (emit_case_nodes): Don't omit the conditional branch to default where needed to
+                                    handle case ranges correctly.
+
+2004-06-20 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.3-tigcc-3 released as part of TIGCC 0.95 Beta 11.
+
+2004-06-20 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k.c (m68k_coff_asm_named_section): Handle rodata sections properly
+	                                                    with -fdata-sections.
+	* varasm.c (asm_emit_uninitialised): Don't manually create sections for common symbols
+	                                     under -fdata-sections, the linker does it anyway.
+	    (assemble_variable): Likewise.
+	    (categorize_decl_for_section): Handle -fzero-initialized-in-bss correctly.
+
+2004-06-19 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k_ti.h (TRAMPOLINE_ADJUST_ADDRESS): Don't hardcode 0x40000, let TIGCCLIB
+	    compute the offset. Remove the ghost space warning, this is now handled automatically
+	    by TIGCCLIB.
+
+	* toplev.c (process_options): Remove pointless warning about -ffunction-sections and
+	                              debugging on some targets (not ours!).
+
+	* config/m68k/m68k.c (m68k_coff_asm_named_section): Handle BSS sections properly with
+	                                                    -fdata-sections.
+
+2004-04-15 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.3-tigcc-2 released as part of TIGCC 0.95 Beta 7.
+
+2004-04-05 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* calls.c (expand_call): Revert broken PR 8081 patch (2003-09-02/2004-02-11).
+
+2004-03-13 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.3-tigcc-1 released as part of TIGCC 0.95 Beta 6.
+
+2004-02-22  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	Fix -mpcrel support:
+	* config/m68k/m68k.md (2 anonymous PIC call sequence patterns): Don't use bsr.l under
+	    -mpcrel. Use jbsr instead and let the assembler sort it out.
+	* config/m68k/m68k.c (m68k_output_mi_thunk): Use jra instead of bra.l under -mpcrel.
+
+	* config/m68k/m68k.md (3 anonymous patterns for cmp): Don't force addressing to be
+	                                                      absolute.
+	    (ashrdi_const): Fix %d0 typo/thinko.
+
+	* config/m68k/m68k.md (indirect_jump): Use jra instead of jmp. Don't add (%pc) under
+	                                       -mpcrel (using "%A0").
+	* config/m68k/m68k.c (print_operands): Add %A letter to support this.
+
+	* config/m68k/m68k.c (extended_address_operand): New function.
+	* config/m68k/m68k-protos.h (extended_address_operand): Add prototype.
+	* config/m68k/m68k.h (PREDICATE_CODES): Add extended_address_operand.
+	* config/m68k/m68k.md (indirect_jump): Use it.
+
+2004-02-22  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+ 	* config/m68k/m68k-ti.h (ASM_FILE_START): Don't global-import __reg_relative, current
+	                                          tigcc.a only exports __reg_relative_an.
+
+2004-02-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k-ti.h (ASM_FILE_START): Use __ld_entry_point_plus_0x8000 as __relation.
+
+2004-02-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3.3 release.
+
+2004-02-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k.c (output_move_double): Fix 10-byte fp stack pushes.
+
+2004-02-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* c-format.c (printf_length_specs): Remove modifiers not supported by AMS.
+	    (printf_flag_specs, print_char_table, format_types): Likewise. Add AMS extensions.
+	    (scanf_length_specs): Remove modifiers not supported by my *scanf implementation.
+	    (scanf_flag_specs, scan_char_table, format_types): Likewise.
+	    (print_char_table): Mark %y and %Y as extensions, add %r and %R.
+	* builtin-attrs.def: Add list of 5. Add list pairs of 4,0 and 4,5. Add nonnull at 4.
+	                     Move vscanf, vfscanf, vsscanf to C89. Add vcbprintf, cbprintf,
+	                     vcbscanf, cbscanf.
+
+2004-02-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Backport from mainline:
+	2003-04-16  J"orn Rennecke <joern.rennecke@superh.com>
+
+		Re-apply this patch:
+
+		2002-05-16  Dale Johannesen  <dalej@apple.com>
+		  * combine.c (cant_combine_insn_p):  Reenable combinations
+		  involving hard regs unless CLASS_LIKELY_SPILLED_P.
+
+2004-02-11  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* c-format.c (print_char_table): Remove %o.
+
+2004-02-11  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	Apply proposed patch for PR 8081:
+	2003-09-02 Sitikant Sahu  <sitikants@noida.hcltech.com>
+
+		* calls.c (expand_call): Allocate dynamically on stack for
+		variable size structure return (PR 8081).
+
+2004-02-11  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	Backport from mainline:
+	2004-01-11  Andreas Schwab  <schwab@suse.de>
+
+		* config/m68k/m68k.c (output_move_const_into_data_reg): Clear cc
+		status for NOTB/NOTW/NEGW methods.
+
+2004-02-10  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3.3 20030209 snapshot.
+	* Don't configure with --with-gnu-ld, there is no point in lying about the linker we use.
+
+2004-01-06 Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre26 released as part of TIGCC 0.95 Beta 5.
+
+2004-01-04  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* cppdefaults.c (struct cpp_include_defaults): Disable hardcoded prefixes.
+	    (GCC_INCLUDE_DIR, GCC_INCLUDE_DIR_LEN): Disable hardcoded prefix.
+	* gcc.c (STANDARD_EXEC_PREFIX, STANDARD_STARTFILE_PREFIX, TOOLDIR_BASE_PREFIX,
+	         STANDARD_BINDIR_PREFIX, standard_exec_prefix, standard_exec_prefix_1,
+	         md_exec_prefix, md_startfile_prefix, md_startfile_prefix_1,
+	         standard_startfile_prefix, standard_startfile_prefix_1,
+	         standard_startfile_prefix_2, tooldir_base_prefix, tooldir_prefix,
+	         standard_bindir_prefix): Disable.
+	    (struct static_specs): Disable md_exec_prefix, md_startfile_prefix,
+	                           md_startfile_prefix_1 and startfile_prefix_spec.
+	    (int warn_std_ptr): Disable unused variable.
+	    (process_command): Don't use environment variables. Don't hardcode any prefix at
+	                       compile time.
+	    (main): Likewise.
+
+2003-12-28  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* unroll.c (loop_iterations): Subtract 1 from n_iterations in unrotated (-Os) loop.
+            Optimize case where n_iterations ends up 0 after subtracting 1 by deleting the loop.
+
+2003-11-24  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre25 released as part of TIGCC 0.95 Beta 4.
+
+2003-11-16  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* real.c (bcdppmul): Handle resultl carry greater than 1 (if->while). Add sanity check.
+	  (bcdmul) Unswap operands for the neg*pos case.
+	  (bcddiv) Unswap operands for the neg/pos case.
+
+2003-10-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre24 released as part of TIGCC 0.95 Beta 3.
+
+2003-10-25  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* real.c (bcdpdroplast): Remove.
+          (bcdpadd1ulp): New function.
+          (bcdppadd): Don't use bcdpdroplast. Do the rounding at the end, using bcdpadd1ulp.
+          (bcdpnorm): Remove. Inline into bcdppsub.
+          (bcdppsub): Don't use bcdpdroplast. Do the rounding at the end, during normalization.
+                      Also handle extra digits there. Don't use bcdpnorm.
+
+	* real.c (bcdppadd): Avoid shift count overflow.
+	  (bcdppsub): Likewise.
+
+2003-10-21  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre23 prepared for release (but not released).
+
+2003-10-21  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* real.c (bcdppmul): Fix exponent off-by-one.
+	  (bcdppdiv): Fix typo in multiplication of divisor by 2^56.
+	              Add missing reinitialization of factor in loop to compute divisorl.
+	              Fix off-by-one when checking if the divisor fits (need <=, not <).
+
+2003-10-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre22b released as part of TIGCC 0.95 Beta 2 r1 for *nix
+
+2003-10-19  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* real.c (bcdppadd, bcdppsub, bcdppmul, bcdppdiv): Don't initialize a structure with a
+	    non-constant initializer, GCC 2 doesn't like that.
+
+2003-10-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre22a released as part of TIGCC 0.95 Beta 2
+
+2003-10-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* toplev.c (flag_zero_initialized_in_bss): Make default off.
+
+2003-10-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre22 prepared for release (but not released).
+
+2003-10-12  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* real.c (bcdppmul, bcdmul, bcdppdiv, bcddiv): New static functions.
+          (real_arithmetic): Use bcdmul for multiplication and bcddiv for division. Drop obsolete
+                             hack using host floating point.
+          (exact_real_inverse): Use bcddiv for the division. Only do the optimization if the
+                                inverse actually _is_ exact.
+	* config/smapbcd.h (ZERO, UNSIGNED_ZERO, POSITIVE_ZERO, NEGATIVE_ZERO, UNSIGNED_INF,
+                            POSITIVE_INF, NEGATIVE_INF, NAN, REAL_VALUES_LESS, REAL_VALUE_LDEXP,
+                            REAL_VALUE_UNSIGNED_FIX, REAL_VALUE_RNDZINT, REAL_VALUE_DTOF,
+                            REAL_VALUE_HTOF, REAL_VALUE_NEGATE): Add __extension__ to shut up
+                                                                 some -pedantic warnings.
+          (MODE_HAS_NANS, MODE_HAS_INFINITIES, MODE_HAS_SIGNED_ZEROS): Define.
+	* Revert local patches merged 2002-12-26:
+		* toplev.c: Include setjmp.h.
+		  (float_signal): Revert removal.
+		  (float_handler_set, float_handled, float_handler): Likewise.
+		  (set_float_handler): Likewise.
+		  (general_init): Set SIGFPE to float_handler, not crash_handler.
+		* toplev.h (set_float_handler): Add prototype.
+
+2003-10-11  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Revert local patches merged 2002-12-26:
+		* fold-const.c (const_binop): Don't use REAL_ARITHMETIC.
+		* tree.h (struct real_value): Disable.
+		  (struct smap_bcd_float): Declare.
+		  (TREE_REAL_CST): Add cast to (REAL_VALUE_TYPE *) to convert struct smap_bcd_float
+		                   to the typedef'ed smap_bcd_float.
+		  (struct tree_real_cst): Use struct smap_bcd_float instead of struct real_value.
+		* rtl.h (smap_bcd_float): Declare.
+		  (CONST_DOUBLE_REAL_VALUE): Use smap_bcd_float instead of struct real_value.
+	* real.h (struct real_value): Comment out definition, add own definition instead.
+	* config/smapbcd.h (smap_bcd_float): Typedef to struct real_value. Remove old typedef.
+	* real.c (bcdpdroplast, bcdpnorm, bcdppadd, bcdppsub, bcdadd, bcdsub, bcdmin, bcdmax): New
+                     static functions.
+          (real_arithmetic): Use bcdadd, bcdsub, bcdmin and bcdmax for addition, subtraction, min
+                             and max (respectively).
+
+2003-10-10  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre21 prepared for release (but not released).
+
+2003-10-10  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Revert local patches merged 2002-12-26:
+		* c-decl.c (pushdecl): If compiled using "nostub" mode, set a flag.
+		* config/m68k/m68k.h:
+		  (MASK_BADLINK, TARGET_BADLINK): Define.
+		  (MASK_NOSTUB, TARGET_NOSTUB): Define.
+	* config/m68k/m68k.h: (TARGET_SWITCHES): Remove no longer supported "badlink" and "mlink"
+	                                         switches (and their negatives).
+	* Revert:
+	  2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+		* config/m68k/coff.h (BSS_SECTION_ASM_OP): Disable.
+		  (ASM_OUTPUT_ALIGNED_BSS): Likewise.
+	* config/m68k/m68k-coff.h: (TARGET_DEFAULT): Remove MASK_BADLINK.
+	* config/m68k/m68k-ti.h: (ASM_OUTPUT_COMMON): Don't use TARGET_BADLINK and TARGET_NOSTUB.
+	  (ASM_OUTPUT_LOCAL): Likewise.
+	  (BSS_SECTION_ASM_OP): Redefine, handle TARGET_NO_BSS.
+
+2003-10-09  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre20 prepared for release (but not released).
+
+2003-10-09  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k-ti.h (ASM_FILE_START): Adapt -freg-relative code for the new linker.
+
+2003-10-08  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/smapbcd.h (REAL_VALUE_TO_STRING): Use "%08lx", not "%lx".
+	  (REAL_VALUE_ATOF): Call REAL_VALUE_HTOF for hex floats or REAL_VALUE_DTOF for decimal
+	                     floats. Rename original to...
+	  (REAL_VALUE_DTOF): ...this new macro.
+	  (REAL_VALUE_HTOF): Detect host floating point overflow.
+	* fold-const.c (const_binop): Likewise.
+	* real.c (real_arithmetic): Likewise.
+	  (exact_real_inverse): Likewise.
+
+2003-10-07  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* cppinit.c (cpp_read_main_file): Always disable "standard" include directory processing.
+
+2003-09-08  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre19 released.
+
+2003-09-07  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* stmt.c (expand_end_case_type): Don't balance the tree when optimizing for size.
+	                                 A linear decision tree gives far smaller code.
+	  (emit_case_nodes): Omit the conditional branch to default if we are optimizing for size.
+
+2003-09-06  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	Backport from mainline (3.4):
+
+	2003-08-30  Steven Bosscher  <steven@gcc.gnu.org>
+		    Roger Sayle  <roger@eyesopen.com>
+
+		PR middle-end/11823
+		* stmt.c (expand_end_case_type): Only use jump tables for dense
+		switch statements when optimizing for size.
+
+2003-07-05  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre18 released.
+
+2003-07-05  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k.h (MULW_COST): Decrease multiplication cost under -Os.
+	  (DIVW_COST): Decrease division cost under -Os.
+	  (UDIVW_COST): Likewise.
+	  (RTX_COSTS): Adjust shift costs under -Os. Distinguish signed vs. unsigned division.
+
+2003-06-27  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre17 released.
+
+2003-06-27  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3.1 20030623 snapshot.
+	* config/m68k/m68k.h (MASK_NO_BSS, TARGET_NO_BSS): Define.
+	  (TARGET_SWITCHES): Add -mno-bss, -mnobss, -mbss.
+	* config/m68k/m68k_ti.h (ASM_OUTPUT_COMMON, ASM_OUTPUT_LOCAL): Use them.
+
+2003-06-07  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre16 released.
+
+2003-06-07  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Disabled the following patch:
+
+	  2003-03-21  Richard Henderson  <rth@redhat.com>
+
+		PR opt/2001
+		* bb-reorder.c (maybe_duplicate_computed_goto_succ): New.
+		(make_reorder_chain_1): Call it.
+
+		* function.h (struct function): Add computed_goto_common_label,
+		computed_goto_common_reg.
+		* function.c (free_after_compilation): Zap them.
+		* stmt.c (expand_computed_goto): Use them to produce one
+		indirect branch per function.
+
+2003-06-06  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre15 released.
+
+2003-06-06  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/m68k.h (MASK_MERGE_TO_DATA, TARGET_MERGE_TO_DATA): Define.
+	  (TARGET_SWITCHES): Add -mmerge-to-data, -mno-merge-to-data, -mnomerge-to-data.
+	* config/m68k/m68k_ti.h (TEXT_SECTION_ASM_OP): Use them.
+	  (DATA_SECTION_ASM_OP): Use them. Add.
+	  (ASM_FILE_START): Use them.
+	* config/m68k/m68k.h (MASK_RODATA_TO_TEXT, TARGET_RODATA_TO_TEXT): Define.
+	  (TARGET_SWITCHES): Add -mrodata-to-text, -mno-rodata-to-text, -mnorodata-to-text.
+	* config/m68k/m68k_ti.h (READONLY_DATA_SECTION_ASM_OP): Define.
+	  (JUMP_TABLES_IN_TEXT_SECTION): Define to 1.
+	* real.h (significand_size): Fix definition.
+
+2003-06-06  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3.1-pre14 released.
+
+2003-06-06  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3.1 20030602 snapshot.
+	* unroll.c (unroll_loop): Delete unconditional jump first.
+
+2003-04-23  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre13 released.
+
+2003-04-23  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* builtin_attrs.def: Add predefined attributes for *printf and *scanf (removed in FSF
+	  GCC) back.
+	* builtins.def: Disable new *printf and *scanf builtins (added to FSF GCC).
+
+2003-04-21  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3 20030421 snapshot.
+	* Revert the following patch (added to FSF GCC):
+	  Wed Mar  5 15:45:40 CET 2003  Jan Hubicka  <jh@suse.cz>
+
+	          * toplev.c (rest_of_compilation):  Do duplicate loop headers when
+	            optimizing for size.
+
+2003-03-16  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre12 released.
+
+2003-03-16  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Applied the following proposed patch for PR 7871 (and 7595):
+	  2003-03-10  James E Wilson  <wilson@tuliptree.org>
+
+	           * flow.c (mark_set_1): Handle global_regs like the frame pointer.
+
+2003-03-15  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* expr.c (emit_block_move_libcall_fn): Use emit_library_call.
+	  (clear_storage_libcall_fn): Likewise.
+
+2003-03-04  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre11 released.
+
+2003-03-04  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3 20030303 snapshot.
+
+2003-02-20  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre10 released.
+
+2003-02-20  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* final.c (alter_subreg): On big-endian machines, adjust offset of paradoxical
+	                          subregs of memory to point to the correct place.
+
+2003-02-14  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre9 released.
+
+2003-02-14  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gcse.c (do_local_cprop): Handle global register variables.
+
+2003-02-14  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre8 released.
+
+2003-02-14  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3 20030210 snapshot.
+	* gcse.c (do_local_cprop): Revert 20030104 patch. (Fixed differently in FSF tree.)
+
+2003-01-04  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre7 released.
+
+2003-01-04  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge with GCC 3.3 20031230 snapshot.
+	* config/m68k/m68k_ti.h (TRAMPOLINE_ADJUST_ADDRESS): Add.
+	* builtin-attrs.def: Add definitions for printf, fprintf.
+	* c-format.c (check_format_types): Account for *printf and *scanf not actually supporting
+                                           -mlong. Fix misplaced parentheses.
+
+2003-01-01  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre6 released.
+
+2003-01-04  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* gcse.c (do_local_cprop): Don't touch %sp.
+
+2002-12-27  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre5 released.
+
+2002-12-27  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* cppmacro.c (replace_args): Add missing "macro = node->value.macro;".
+	* local-alloc.c (update_equiv_regs): Put abort back.
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre4 released.
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* c-opts.c (COMMAND_LINE_OPTIONS): Change -fno-auto-octals to -fauto-octals.
+	  (c_common_decode_option): Likewise. Use preprocessor option.
+	* cppinit.c: Add no_auto_octals option.
+	* flags.h (flag_auto_octals): Remove.
+	* toplev.c (flag_auto_octals): Remove.
+	  (struct f_options): Remove auto-octals.
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre3 prepared for release (but not released).
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* cpplib.c (_cpp_init_internal_pragmas): Define #pragma poison in the global namespace.
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre2 prepared for release (but not released).
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* config/m68k/coff.h (BSS_SECTION_ASM_OP): Disable.
+	  (ASM_OUTPUT_ALIGNED_BSS): Likewise.
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* 3.3-pre1 prepared for release (but not released).
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Merge TIGCC patchset (1999-2002; changes by Jean Canazzi, François
+	  Révol, Sebastian Reichelt, Zeljko Juric and me; some changes by
+	  Fred Fish dated 1998-01-21 imported from AmigaOS-GCC):
+		* attribs.c (decl_attributes): Use modified build_type_attribute_variant instead
+		                               of build_type_copy.
+		* builtin-attrs.def (expand_builtin_fputs): Disable. Also disable prototype.
+		  (fold_builtin_inf, fold_builtin_nan): Likewise.
+		  (expand_builtin): Don't use expand_builtin_fputs.
+		  (fold_builtin): Don't use fold_builtin_inf, fold_builtin_nan.
+		  (apply_args_size): Don't use register passing for __builtin_apply.
+		* builtins.def: Disable stdio builtins.
+		* c-common.c (builtin_define_with_hex_fp_value): Disable. Also disable prototype.
+		  (is_valid_printf_arglist): Likewise.
+		  (c_expand_builtin_printf, c_expand_builtin_fprintf): Likewise.
+		  (c_expand_builtin): Don't use c_expand_builtin_printf, c_expand_builtin_fprintf.
+		  (builtin_define_float_constants): Disable contents. Do nothing.
+		* c-decl.c (pushdecl): If compiled using "nostub" mode, set a flag.
+		  (push_parm_decl): Add asmspec to support explicit register specification of 
+		                    parameters, and use when set.
+		  (build_compound_literal): Handle -fglobal-compound-literals.
+		* c-format.c (print_char_table, scan_char_table): Add TI-specific formats.
+		                                                  Remove unsupported formats.
+		  (check_format_types): Don't warn about differences in floating point format;
+		                        they're all the same.
+		* c-lex.c (interpret_float): Don't use real_from_string, real_convert. Use
+		                             REAL_VALUE_ATOF instead.
+		* c-opts.c (COMMAND_LINE_OPTIONS): Add -fno-auto-octals.
+		  (c_common_decode_option): Handle -fno-auto-octals.
+		* c-parse.in (parms, parm, firstparm, myparms, my parm): Add support for explicit
+		    register specification for parameters.
+		  (absdcl_maybe_attribute): Likewise, rename to absdcl_maybeasm_maybe_attribute.
+		  Fix %expect directive.
+		* c-pretty-print.c (pp_c_real_literal): Use REAL_VALUE_TO_STRING instead of
+		                                        real_to_decimal.
+		* c-tree.h: (push_parm_decl): Add type of asmspec to prototype.
+		* c-typeck.c (undeclared_variable_notice): Remove.
+		  (build_external_ref): Remove redundant undeclared variable notice.
+		  (default_function_array_conversion): Handle -fglobal-compound-literals.
+		  (build_unary_op): Likewise.
+		  (error_init): Use one-line instead of two-line diagnostic.
+		  (pedwarn_init): Likewise.
+		  (warning_init): Likewise.
+		* collect2.c: Applied patch to allow collect2 to build on MinGW by Lev Serebryakov
+		              (2002-10-25).
+		* config/dbxcoff.h (ASM_OUTPUT_SOURCE_LINE): Use absolute rather than
+		    function-relative COFF line numbers if TARGET_COFFABSLINES.
+		* config/m68k/m68k-coff.h: (TARGET_CPU_DEFAULT, TARGET_DEFAULT): Define.
+		  Include m68k-ti.h instead of m68kemb.h.
+		* config/m68k/m68k-ti.h: New file. Defines AMS-specific target settings.
+		* config/m68k/m68k.c:
+		  Add support for '-mregparm' and explicit register specification for parameters:
+		    (comp_m68k_type_attributes): New function. Add prototype.
+		    (comp_amigaos_type_attributes): Likewise.
+		    (m68k_regparm_string, m68k_regparm): New variables.
+		    (override_options): Validate -mregparm and -mregparm= value.
+		    (m68k_init_cumulative_args, amigaos_init_cumulative_args): New functions.
+		    (m68k_function_arg_advance, amigaos_function_arg_advance): Likewise.
+		    (m68k_function_arg, amigaos_function_arg): Likewise.
+		  Add support for __attribute__((regparm)) and __attribute__((stkparm)):
+		    (TARGET_ATTRIBUTE_TABLE): Define.
+		    (TARGET_COMP_TYPE_ATTRIBUTES): Define.
+		    (m68k_attribute_table): New array.
+		    (m68k_handle_stkparm_attribute): New function. Add prototype.
+		    (m68k_handle_regparm_attribute): Likewise.
+		  Add AMS floating point support:
+		    (override_options): Don't select any flavor of XFmode.
+		    (output_move_himode_const): New function.
+		    (halfsinglemove_string): Likewise.
+		    (output_move_double): Handle BFmode.
+		    (floating_exact_log2): Disable contents. Abort if called.
+		    (print_operand): Disable handling of SFmode, DFmode, XFmode.
+		    (const_uint32_operand): Don't handle CONST_DOUBLE.
+		                            Check for "INTVAL (op) >= 0" (possibly wrong?).
+		  Add support for -freg-relative:
+		    (TARGET_RELATION_REG): Declare, initialize.
+		    (print_operand): Handle TARGET_REG_RELATIVE.
+		* config/m68k/m68k.h:
+		  Add support for '-mregparm' and explicit register specification for parameters:
+		    Update comment about TARGET_REGPARM.
+		    (TARGET_SWITCHES): Add "regparm", "noregparm", "no-regparm".
+		    (TARGET_OPTIONS): Add "regparm=".
+		    (EXPLICIT_REGPARM): Define.
+		    (FUNCTION_ARG_REGNO_P): Handle register parameters.
+		    (struct m68k_args): New structure.
+		    (CUMULATIVE_ARGS): Use it.
+		    (M68K_MAX_REGPARM): Define to 6.
+		    (M68K_DEFAULT_REGPARM): Define to 4.
+		    (INIT_CUMULATIVE_ARGS): Use amigaos_init_cumulative_args.
+		    (FUNCTION_ARG_ADVANCE): Use amigaos_function_arg_advance.
+		    (FUNCTION_ARG): Use amigaos_function_arg.
+		    (FUNCTION_ARG_PARTIAL_NREGS): Change to always 0.
+		    (m68k_regparm_string, m68k_regparm): Declare as extern.
+		  Add support for -freg-relative:
+		    (TARGET_RELATION_REG): Declare as extern.
+		  (MASK_TIOS, TARGET_TIOS): Define.
+		  (MASK_DIRECTFLOAT, TARGET_DIRECTFLOAT): Define.
+		  (MASK_REG_RELATIVE, TARGET_REG_RELATIVE): Define.
+		  (MASK_BADLINK, TARGET_BADLINK): Define.
+		  (MASK_COFFABSLINES, COFFABSLINES): Define.
+		  (MASK_NOSTUB, TARGET_NOSTUB): Define.
+		  (MASK_MERGE_SECTIONS, TARGET_MERGE_SECTIONS): Define.
+		  (TARGET_SWITCHES): Add "long", "badlink", "mlink", "tios", "merge-sections" and
+		                     negations, "no-pcrel", "coff-abslines".
+		  (PARM_BOUNDARY): Set to 16 independently of TARGET_SHORT.
+		  (ASM_OUTPUT_COMMON): Guard with #ifndef.
+		  (ASM_OUTPUT_LOCAL): Likewise.
+		  (VALID_MACHINE_TYPE_ATTRIBUTE, COMP_TYPE_ATTRIBUTES): Add, but disabled.
+		* config/m68k/m68k.md (movbf): New define_expand for AMS floating point support.
+		  (unnamed BF move): New define_insn for AMS floating point support.
+		* config/m68k/smapbcd.h: New file. Defines macros for AMS floating point support.
+		* cppexp.c (cpp_classify_number): Handle binary numbers and -fno-auto-octals.
+		  (cpp_interpret_integer): Handle binary numbers.
+		* cpphash.h (mls_line, mls_col): Revert removal.
+		* cpplex.c (unterminated): Likewise.
+		  (parse_string): Revert removal of multi-line strings. Use "unterminated".
+		* cpplib.h (struct cpp_options): Add no_auto_octals.
+		  (CPP_N_BINARY): Define.
+		* cppmacro.c (replace_args): If 'SYMSTR' is used with a string literal, convert
+		                             automatically to 'SYMSTR_CONST'.
+		* cppmain.c (scan_translation_unit): Revert removal of multi-line strings.
+		* diagnostic.c (internal_error): Change bug report instructions.
+		* dwarf2out.c (add_const_value_attribute): Handle BFmode (AMS floating point).
+		* emit-rtl.c (const_double_htab_eq): Use REAL_VALUES_IDENTICAL instead of
+		                                     real_identical.
+		  (gen_lowpart_common): Disable handling of floating point. Handle BFmode instead.
+		  (constant_subword): Disable handling of floating point.
+		  (operand_subword): Handle BFmode (AMS floating point).
+		* explow.c (copy_to_mode_reg): Handle BFmode by calling convert_move.
+		* expr.c (convert_move): Add BFmode (AMS floating point) libcalls.
+		  (convert_modes): Handle BFmode (AMS floating point).
+		  (emit_block_move_via_libcall): Pass short integers to bcopy even if -mlong.
+		  (emit_block_move_libcall_fn): Likewise.
+		  (expand_assignment): Likewise.
+		  (clear_storage_via_libcall): Pass short integers to bzero even if -mlong.
+		  (clear_storage_libcall_fn): Likewise.
+		  (compress_float_constant): Don't call exact_real_truncate. Disable code using it.
+		  (emit_push_insn): Don't take a modulus by 0. Set offset to constant 0 instead.
+		  (is_zeros_p): Use REAL_VALUE_ISZERO instead of REAL_VALUES_IDENTICAL.
+		* final.c (output_asm_insn): Add support for -freg-relative.
+		  (split_double): Disable code which doesn't work for AMS floats. Abort if reached.
+		* flags.h (flag_auto_octals, flag_global_compound_literals): Declare extern.
+		* flow.c (regno_uninitialized): Support explicit register specification of
+		                                parameters.
+		* fold-const.c (const_binop): Don't use REAL_ARITHMETIC.
+		                              Use REAL_VALUE_TRUNCATE instead of
+		                              real_value_truncate.
+		  (fold_convert): Don't fold real to integer conversion, as the required functions
+		                  are not implemented.
+		                  Use REAL_VALUE_TRUNCATE instead of real_value_truncate.
+		  (fold): Use temporaries for REAL_VALUE_NEGATE and REAL_VALUE_NEGATIVE because of
+		          side effects.
+		* function.c (function_arg_regno_p): New function for explicit register
+		                                     specification of parameters.
+		* gcc.c (process_command): Don't try to create gcc_exec_prefix from argv[0].
+		  (main): Don't load specs from exec prefix. Always use builtin specs.
+		* libfuncs.h (enum libfunc_index): Add BFmode (AMS floating point) libcalls.
+		  Define extendsfbf2_libfunc etc.
+		* local-alloc.c (update_equiv_regs): Disable abort.
+		* machmode.def: Add BFmode (AMS floating point) to the machine modes.
+		* optabs.c (expand_binop): Don't look for a wider mode for floating point numbers.
+		  (expand_twoval_binop): Likewise.
+		  (expand_unop): Likewise.
+		  (prepare_float_lib_cmp): Handle BFmode (AMS floating point).
+		  (expand_float): Don't special-case unsigned integers, as the required functions
+		                  are not implemented.
+		                  Handle BFmode (AMS floating point).
+		  (ftruncify): Likewise.
+		  (init_optabs): Initialize extendsfbf2_libfunc etc.
+		* print-rtl.c (print_rtx): Don't use real_to_decimal, real_to_hexadecimal. Use
+		                           REAL_VALUE_TO_STRING.
+		* print-tree.c (print_node_brief): Use REAL_VALUE_TO_STRING instead of
+		                                   real_to_decimal.
+		  (print_node): Likewise.
+		* real.c: Include setjmp.h.
+		  (NULL_PTR): Define.
+		  (REAL_DEBUG_INFO, REAL_DEBUG_SPRINTF): Define.
+		  Disable all static function prototypes.
+		  (real_arithmetic): Replace with own implementation.
+		  (exact_real_inverse): Likewise.
+		  (real_hash): Likewise.
+		  Disable all other functions.
+		  (ereal_to_int, ereal_from_int, ereal_from_uint): New functions.
+		* real.h: Include smapbcd.h.
+		  (SMAP_BCD_FLOAT_FORMAT): Define.
+		  (REAL_WIDTH): Change definition to correspond to AMS floating point.
+		  (ereal_to_int, ereal_from_int, ereal_from_uint): Add prototypes.
+		  Disable everything else except the prototypes of real_arithmetic,
+		  exact_real_inverse, real_hash, real_value_from_int_cst,
+		  const_double_from_real_value, build_real, the REAL_VALUE_FROM_CONST_DOUBLE and
+		  CONST_DOUBLE_FROM_REAL_VALUE macros and the dconst0, dconst1, dconst2, dconstm1
+		  externs.
+		* rtl.h (smap_bcd_float): Declare.
+		  (CONST_DOUBLE_REAL_VALUE): Use smap_bcd_float instead of struct real_value.
+		* sdbout.c (sdbout_source_line): Use absolute, not function-relative, lines by
+		                                 default.
+		* simplify-rtx.c (simplify_unary_operation): Use REAL_VALUE_TRUNCATE instead of
+		                                             real_value_truncate.
+		  (simplify_binary_operation): Likewise.
+		* toplev.c: Include setjmp.h.
+		  (float_signal): Revert removal.
+		  (float_handler_set, float_handled, float_handler): Likewise.
+		  (set_float_handler): Likewise.
+		  (flag_auto_octals, flag_global_compound_literals): Initialize
+		  (struct f_options): Add auto-octals, global-compound-literals,
+		                      global-cast-constructors.
+		  (decode_f_option): Add support for -freg-relative.
+		  (general_init): Set SIGFPE to float_handler, not crash_handler.
+		  (parse_options_and_default_flags): Set %d2 to call-used if TARGET_TIOS.
+		* toplev.h (set_float_handler): Add prototype.
+		* tree.c (real_zerop): Use REAL_VALUE_ISZERO instead of REAL_VALUES_EQUAL.
+		* tree.h (struct real_value): Disable.
+		  (struct smap_bcd_float): Declare.
+		  (TREE_REAL_CST): Add cast to (REAL_VALUE_TYPE *) to convert struct smap_bcd_float
+		                   to the typedef'ed smap_bcd_float.
+		  (struct tree_real_cst): Use struct smap_bcd_float instead of struct real_value.
+		* varasm.c (assemble_real): Handle BFmode (AMS floating point).
+		  (const_hash_1): Add sanity check (code must not be zero).
+		  (decode_rtx_const): Use members of smap_bcd_float, not struct real_value, for
+		                      member-by-member copying.
+		* version.c (version_string): Add "TIGCC".
+		  (bug_report_url): Change from gnu.org URL to tigcc.ticalc.org URL.
+
+2002-12-26  Kevin Kofler  <Kevin@tigcc.ticalc.org>
+
+	* Import GCC 3.3 20021223 snapshot.

+ 1 - 0
tigcc/gcc/Makefile-empty

@@ -0,0 +1 @@
+all:

+ 131 - 0
tigcc/gcc/cleansources.sh

@@ -0,0 +1,131 @@
+rm -f .brik
+rm -f md5.sum
+rm -f -r INSTALL
+ls -A config/mh-* >tmpfiles.lst
+for name in `grep -v -e "cygwin" -e "mingw" tmpfiles.lst`; do rm -f "$name"; done
+rm -f config/mpw-mh-mpw
+ls -A config/mt-* >tmpfiles.lst
+for name in `grep -v -e "m68k" tmpfiles.lst`; do rm -f "$name"; done
+rm -f -r contrib
+ls -A gcc/config/ >tmpfiles.lst
+for name in `grep -v -e "^i386$" -e "^m68k$" -e "README" -e "install" -e "libgcc-glibc" -e "dbx" -e "usegas" tmpfiles.lst`; do rm -f -r "gcc/config/$name"; done
+ls -A gcc/config/i386/ >tmpfiles.lst
+for name in `grep -v -e "x-cygwin" -e "xm-cygwin" -e "xm-mingw" tmpfiles.lst`; do rm -f "gcc/config/i386/$name"; done
+ls -A gcc/config/m68k/ >tmpfiles.lst
+for name in `grep -v -e "m68k\.c" -e "t-m68kbare" -e "m68k\.md" -e "^m68k\.h" -e "m68k-coff" -e "m68k-none" -e "m68k-protos" -e "coff\.h" tmpfiles.lst`; do rm -f "gcc/config/m68k/$name"; done
+rm -f -r gcc/fixinc
+rm -f -r gcc/ginclude
+rm -f -r gcc/po
+rm -f -r gcc/doc
+rm -f -r gcc/treelang
+rm -f -r libiberty/testsuite
+rm -f -r maintainer-scripts
+rm -f -r bfd/doc
+rm -f -r bfd/po
+rm -f bfd/hosts/*.c
+rm -f bfd/hosts/*.h
+rm -f -r binutils
+rm -f -r etc
+rm -f -r gas/doc
+rm -f -r gas/po
+rm -f -r gas/testsuite
+rm -f -r gprof
+rm -f -r include/nlm
+rm -f -r include/regs
+rm -f -r ld
+rm -f -r opcodes/po
+rm -f -r texinfo
+rm -f bfd/*bout*
+rm -f bfd/*aix*
+rm -f bfd/*386*
+rm -f bfd/*linux*
+rm -f bfd/*lynx*
+rm -f bfd/*cisco*
+rm -f bfd/*svm68k*
+rm -f bfd/*mach*
+rm -f bfd/*mmo*
+rm -f bfd/*news*
+rm -f bfd/*osf*
+rm -f bfd/*pdp*
+rm -f bfd/*ptrace*
+rm -f bfd/*risc*
+rm -f bfd/*rs6*
+rm -f bfd/*sco5*
+rm -f bfd/*sun*
+rm -f bfd/*trad*
+rm -f bfd/*versados*
+rm -f bfd/efi-*
+rm -f bfd/epoc-*
+rm -f bfd/irix-*
+rm -f bfd/pei-*
+rm -f bfd/pe-*
+rm -f bfd/peX*
+rm -f bfd/hp*
+ls -A bfd/*aout* >tmpfiles.lst
+for name in `grep -v -e "libaout.h" tmpfiles.lst`; do rm -f "$name"; done
+rm -f bfd/*bsd*
+rm -f bfd/*demo64*
+ls -A bfd/*elf* >tmpfiles.lst
+for name in `grep -v -e "elf-bfd.h" tmpfiles.lst`; do rm -f "$name"; done
+rm -f bfd/*go32*
+rm -f bfd/*ieee*
+rm -f bfd/*mpw*
+rm -f bfd/*nlm*
+rm -f bfd/*ns32k*
+rm -f bfd/*oasys*
+rm -f bfd/*pef*
+rm -f bfd/*pei*
+rm -f bfd/*ppc*
+rm -f bfd/*som*
+rm -f bfd/*ticoff*
+rm -f bfd/*vms*
+rm -f bfd/*xcoff*
+rm -f bfd/*xsym*
+rm -f bfd/*xtensa*
+ls -A bfd/coff-* >tmpfiles.lst
+for name in `grep -v -e "m68k" tmpfiles.lst`; do rm -f "$name"; done
+ls -A bfd/cpu-* >tmpfiles.lst
+for name in `grep -v -e "m68k" tmpfiles.lst`; do rm -f "$name"; done
+rm -f gas/*aout*
+rm -f gas/*bout*
+rm -f gas/*elf*
+rm -f gas/config/e-*
+rm -f gas/config/*aout*
+rm -f gas/config/*bout*
+rm -f gas/config/*vax*
+rm -f gas/config/*vms*
+rm -f gas/config/*mips*
+rm -f gas/config/*m88k*
+rm -f gas/config/*xtensa*
+ls -A gas/config/obj-* >tmpfiles.lst
+for name in `grep -v -e "generic" -e "obj-coff" tmpfiles.lst`; do rm -f "$name"; done
+ls -A gas/config/te-* >tmpfiles.lst
+for name in `grep -v -e "generic" -e "m68k" tmpfiles.lst`; do rm -f "$name"; done
+ls -A gas/config/tc-* >tmpfiles.lst
+for name in `grep -v -e "generic" -e "m68k" tmpfiles.lst`; do rm -f "$name"; done
+rm -f include/*sim*
+rm -f include/*os9*
+rm -f include/*oasys*
+rm -f include/*bout*
+ls -A include/coff/*.h >tmpfiles.lst
+for name in `grep -v -e "m68k" -e "ecoff" -e "internal" -e "external" -e "sym" tmpfiles.lst`; do rm -f "$name"; done
+ls -A include/opcode/*.h >tmpfiles.lst
+for name in `grep -v -e "m68k" tmpfiles.lst`; do rm -f "$name"; done
+ls -A include/aout/*.h >tmpfiles.lst
+for name in `grep -v -e "aout64.h" -e "ar.h" -e "ranlib.h" -e "stab_gnu.h" tmpfiles.lst`; do rm -f "$name"; done
+ls -A include/elf/*.h >tmpfiles.lst
+for name in `grep -v -e "common.h" -e "dwarf2.h" -e "internal.h" -e "external.h" tmpfiles.lst`; do rm -f "$name"; done
+rm -f -r include/gdb
+rm -f -r include/*mpw*
+rm -f -r include/*ieee*
+rm -f -r include/*xtensa*
+rm -f opcodes/*64*
+rm -f opcodes/*s390*
+rm -f opcodes/*vms*
+rm -f opcodes/*cgen*
+rm -f opcodes/*mpw*
+ls -A opcodes/*.c >tmpfiles.lst
+for name in `grep -v -e "m68k" -e "disass" -e "dis-" tmpfiles.lst`; do rm -f "$name"; done
+ls -A opcodes/*.h >tmpfiles.lst
+for name in `grep -v -e "m68k" -e "disass" -e "dis-" -e "opintl" -e "sysdep" tmpfiles.lst`; do rm -f "$name"; done
+rm -f tmpfiles.lst

+ 1006 - 0
tigcc/gcc/gas-2.14-tigcc-11.diff

@@ -0,0 +1,1006 @@
+diff -Naur binutils-2.14.orig/bfd/config.bfd binutils-2.14.tigcc11/bfd/config.bfd
+--- binutils-2.14.orig/bfd/config.bfd	Mon Jun  2 22:35:20 2003
++++ binutils-2.14.tigcc11/bfd/config.bfd	Sat Jul 12 09:36:42 2003
+@@ -631,7 +631,6 @@
+     ;;
+   m68*-*-coff* | m68*-*-sysv*)
+     targ_defvec=m68kcoff_vec
+-    targ_selvecs="m68kcoff_vec versados_vec ieee_vec"
+     ;;
+   m68*-*-hpux*)
+     targ_defvec=hp300hpux_vec
+diff -Naur binutils-2.14.orig/gas/as.c binutils-2.14.tigcc11/gas/as.c
+--- binutils-2.14.orig/gas/as.c	Tue Apr  8 14:47:06 2003
++++ binutils-2.14.tigcc11/gas/as.c	Wed Jul 16 12:26:28 2003
+@@ -242,6 +242,10 @@
+                       	  s      include symbols\n\
+                       	  =FILE  list to FILE (must be last sub-option)\n"));
+ 
++/* (TIGCC 20030716) */
++  fprintf (stream, _("\
++  --all-relocs            output all relocs, implies --keep-locals (-L)\n"));
++
+   fprintf (stream, _("\
+   -D                      produce assembler debugging messages\n"));
+   fprintf (stream, _("\
+@@ -434,7 +438,10 @@
+ #define OPTION_TARGET_HELP (OPTION_STD_BASE + 19)
+     {"target-help", no_argument, NULL, OPTION_TARGET_HELP},
+ #define OPTION_WARN_FATAL (OPTION_STD_BASE + 20)
+-    {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL}
++    {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL},
++/* (TIGCC 20030716) */
++#define OPTION_ALL_RELOCS (OPTION_STD_BASE + 39)
++    {"all-relocs", no_argument, NULL, OPTION_ALL_RELOCS}
+     /* When you add options here, check that they do not collide with
+        OPTION_MD_BASE.  See as.h.  */
+   };
+@@ -769,6 +776,12 @@
+ 
+ 	case 'X':
+ 	  /* -X means treat warnings as errors.  */
++	  break;
++
++	/* (TIGCC 20030716) */
++	case OPTION_ALL_RELOCS:
++	  flag_all_relocs = 1;
++	  flag_keep_locals = 1; /* implies -L */
+ 	  break;
+ 	}
+     }
+diff -Naur binutils-2.14.orig/gas/as.h binutils-2.14.tigcc11/gas/as.h
+--- binutils-2.14.orig/gas/as.h	Fri Jan 24 01:12:30 2003
++++ binutils-2.14.tigcc11/gas/as.h	Sun Sep  5 01:40:20 2004
+@@ -261,16 +261,22 @@
+ 
+ #ifdef MANY_SEGMENTS
+ #include "bfd.h"
+-#define N_SEGMENTS 40
+-#define SEG_NORMAL(x) ((x) >= SEG_E0 && (x) <= SEG_E39)
+-#define SEG_LIST SEG_E0,SEG_E1,SEG_E2,SEG_E3,SEG_E4,SEG_E5,SEG_E6,SEG_E7,SEG_E8,SEG_E9,\
+-		 SEG_E10,SEG_E11,SEG_E12,SEG_E13,SEG_E14,SEG_E15,SEG_E16,SEG_E17,SEG_E18,SEG_E19,\
+-		 SEG_E20,SEG_E21,SEG_E22,SEG_E23,SEG_E24,SEG_E25,SEG_E26,SEG_E27,SEG_E28,SEG_E29,\
+-		 SEG_E30,SEG_E31,SEG_E32,SEG_E33,SEG_E34,SEG_E35,SEG_E36,SEG_E37,SEG_E38,SEG_E39
++/* (TIGCC 20040625) 40 sections are definitely not enough for
++                    -ffunction-sections, -fdata-sections and the like.
++                    So I increased them to 120. -- Kevin Kofler
++   (TIGCC 20040905) And again to 1024. -- Kevin Kofler */
++#define N_SEGMENTS 1024
++#define SEG_NORMAL(x) ((x) >= SEG_E0 && (x) <= SEG_LAST)
++#define LIST_10_(decade) decade##0,decade##1,decade##2,decade##3,decade##4,decade##5,decade##6,decade##7,decade##8,decade##9
++#define LIST_FIRST_100_(century) LIST_10_(century),LIST_10_(century##1),LIST_10_(century##2),LIST_10_(century##3),LIST_10_(century##4),LIST_10_(century##5),LIST_10_(century##6),LIST_10_(century##7),LIST_10_(century##8),LIST_10_(century##9)
++#define LIST_100_(century) LIST_10_(century##0),LIST_10_(century##1),LIST_10_(century##2),LIST_10_(century##3),LIST_10_(century##4),LIST_10_(century##5),LIST_10_(century##6),LIST_10_(century##7),LIST_10_(century##8),LIST_10_(century##9)
++#define LIST_FIRST_1000_(millennium) LIST_FIRST_100_(millennium),LIST_100_(millennium##1),LIST_100_(millennium##2),LIST_100_(millennium##3),LIST_100_(millennium##4),LIST_100_(millennium##5),LIST_100_(millennium##6),LIST_100_(millennium##7),LIST_100_(millennium##8),LIST_100_(millennium##9)
++#define SEG_LIST LIST_FIRST_1000_(SEG_E),LIST_10_(SEG_E100),LIST_10_(SEG_E101),\
++		 SEG_E1020,SEG_E1021,SEG_E1022,SEG_E1023
+ #define SEG_TEXT SEG_E0
+ #define SEG_DATA SEG_E1
+ #define SEG_BSS SEG_E2
+-#define SEG_LAST SEG_E39
++#define SEG_LAST SEG_E1023
+ #else
+ #define N_SEGMENTS 3
+ #define SEG_NORMAL(x) ((x) == SEG_TEXT || (x) == SEG_DATA || (x) == SEG_BSS)
+@@ -310,8 +316,13 @@
+ #ifdef BFD_ASSEMBLER
+ #define segment_name(SEG)	bfd_get_section_name (stdoutput, SEG)
+ #else
++/* (TIGCC 20040905) Allow arbitrary number of sections here. -- Kevin Kofler */
++#if 0
+ extern char const *const seg_name[];
+-#define segment_name(SEG)	seg_name[(int) (SEG)]
++#define segment_name(SEG)	seg_name[(int) (SEG)]*/
++#else
++char *segment_name PARAMS ((int));
++#endif
+ #endif
+ 
+ #ifndef BFD_ASSEMBLER
+@@ -470,6 +481,9 @@
+ };
+ 
+ extern enum debug_info_type debug_type;
++
++/* (TIGCC 20030716) True if all relocs should be retained.  */
++COMMON unsigned char flag_all_relocs; /* --all-relocs */
+ 
+ /* Maximum level of macro nesting.  */
+ extern int max_macro_nest;
+diff -Naur binutils-2.14.orig/gas/config/obj-coff.c binutils-2.14.tigcc11/gas/config/obj-coff.c
+--- binutils-2.14.orig/gas/config/obj-coff.c	Thu Dec 12 22:46:46 2002
++++ binutils-2.14.tigcc11/gas/config/obj-coff.c	Sun Sep  5 02:04:20 2004
+@@ -1556,7 +1556,7 @@
+      section alignment, then skip this step, as TICOFF does.  */
+   size = bfd_get_section_size_before_reloc (sec);
+   mask = ((bfd_vma) 1 << align_power) - 1;
+-#if !defined(TICOFF)
++#if 0 /*!defined(TICOFF)*/
+   if (size & mask)
+     {
+       bfd_vma new_size;
+@@ -1699,14 +1699,20 @@
+ /* This vector is used to turn a gas internal segment number into a
+    section number suitable for insertion into a coff symbol table.
+    This must correspond to seg_info_off_by_4.  */
++/* (TIGCC 20040625) 40 sections are definitely not enough for
++                    -ffunction-sections, -fdata-sections and the like.
++                    So I increased them to 120. -- Kevin Kofler */
+ 
+ const short seg_N_TYPE[] =
+ {				/* in: segT   out: N_TYPE bits */
++/* (TIGCC 20040905) Allow arbitrary number of sections here. -- Kevin Kofler */
++#if 0
+   C_ABS_SECTION,
+   1,    2,  3,   4,    5,   6,   7,   8,   9,  10,
+   11,  12,  13,  14,  15,  16,  17,  18,  19,  20,
+   21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
+   31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
++#endif /*0*/
+   C_UNDEF_SECTION,		/* SEG_UNKNOWN */
+   C_UNDEF_SECTION,		/* SEG_GOOF */
+   C_UNDEF_SECTION,		/* SEG_EXPR */
+@@ -1716,6 +1722,13 @@
+   C_REGISTER_SECTION,		/* SEG_REGISTER */
+ };
+ 
++short SEGMENT_TO_SYMBOL_TYPE (n) int n;
++{
++  if (!n) return C_ABS_SECTION;
++  else if (SEG_NORMAL(n)) return n-SEG_E0+1;
++  else return seg_N_TYPE[n-(N_SEGMENTS+1)];
++}
++
+ int function_lineoff = -1;	/* Offset in line#s where the last function
+ 				   started (the odd entry for line #0) */
+ 
+@@ -1783,6 +1796,8 @@
+  SEG_DEBUG,
+  SEG_ABSOLUTE,
+  SEG_UNKNOWN,
++/* (TIGCC 20040905) Allow arbitrary number of sections here. -- Kevin Kofler */
++#if 0
+  SEG_E0,  SEG_E1,  SEG_E2,  SEG_E3,  SEG_E4,
+  SEG_E5,  SEG_E6,  SEG_E7,  SEG_E8,  SEG_E9,
+  SEG_E10, SEG_E11, SEG_E12, SEG_E13, SEG_E14,
+@@ -1801,9 +1816,19 @@
+  (segT) 0,
+  (segT) 0,
+  SEG_REGISTER
++#endif /*0*/
+ };
+ 
+-#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
++static segT SEG_INFO_FROM_SECTION_NUMBER PARAMS ((int));
++
++static segT SEG_INFO_FROM_SECTION_NUMBER (n) int n;
++{
++  if (n<=0) return seg_info_off_by_4[n+4];
++  else if (n<=N_SEGMENTS) return n-1+SEG_E0;
++  else if (n<=N_SEGMENTS+6) return n-1;
++  else if (n==C_REGISTER_SECTION) return SEG_REGISTER;
++  else return 0;
++}
+ 
+ static relax_addressT relax_align PARAMS ((relax_addressT, long));
+ 
+@@ -2025,8 +2050,11 @@
+ 					S_GET_NAME (symbol_ptr));
+ 			    }
+ 
++/* (TIGCC 20030715) Don't convert references to references to the section symbol.
++   (TIGCC 20030805) ... except for local symbols!
++ -- Kevin Kofler  */
+ 			  dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+-			  if (dot)
++			  if (dot && S_IS_LOCAL(symbol_ptr))
+ 			    intr.r_symndx = dot->sy_number;
+ 			  else
+ 			    intr.r_symndx = symbol_ptr->sy_number;
+@@ -3094,6 +3122,11 @@
+       tc_frob_coff_symbol (symbolP);
+ #endif
+ 
++      /* (TIGCC 20040725) Clear the SF_LOCAL flag if the symbol is in a
++                          mergeable section. -- Kevin Kofler  */
++     if (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_flags & STYP_MERGEABLE)
++       SF_CLEAR_LOCAL (symbolP);
++
+       /* We must put the external symbols apart. The loader
+ 	 does not bomb if we do not. But the references in
+ 	 the endndx field for a .bb symbol are not corrected
+@@ -3435,7 +3468,7 @@
+   (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG)	\
+    ? get_recorded_alignment (SEG) : 0)
+ #else
+-#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 1
++#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0 /*1*/
+ #endif
+ #endif
+ 
+@@ -3652,7 +3685,9 @@
+ {
+   unsigned int i;
+ 
+-#ifndef COFF_LONG_SECTION_NAMES
++/* (TIGCC 20040625) Use the full name, not the truncated name, for merging of
++                    identically-named sections. -- Kevin Kofler */
++#if 0 /*ndef COFF_LONG_SECTION_NAMES*/
+   char buf[SCNNMLEN + 1];
+ 
+   strncpy (buf, name, SCNNMLEN);
+@@ -3755,6 +3790,9 @@
+ 		case 'w': flags |= STYP_DATA;   break;
+ 		case 'x': flags |= STYP_TEXT;   break;
+ 		case 'r': flags |= STYP_LIT;	break;
++/* (TIGCC 20040724) TIGCC COFF extensions for section flags -- Kevin Kofler */
++		case 'm': flags |= STYP_MERGEABLE;	break;
++		case 'u': flags |= STYP_UNALIGNED;	break;
+ 		default:
+ 		  as_warn(_("unknown section attribute '%c'"),
+ 			  *input_line_pointer);
+@@ -3915,6 +3953,13 @@
+       symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+       symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
+     }
++
++  /* (TIGCC 20030717) In all-relocs mode, add an __ld_all_relocs symbol pointing
++                      to a dummy label in the text section. -- Kevin Kofler  */
++  if (flag_all_relocs) {
++    symbolP = symbol_new("__ld_all_relocs", SEG_TEXT, 0, &zero_address_frag);
++    S_SET_EXTERNAL(symbolP); /* make it an xdef */
++  }
+ }
+ 
+ /* Build a 'section static' symbol.  */
+@@ -4291,10 +4336,13 @@
+ #endif /* TC_I960 */
+ 	      add_number += S_GET_VALUE (add_symbolP) -
+ 		S_GET_VALUE (sub_symbolP);
+-	      add_symbolP = NULL;
+ 
+ 	      if (!TC_FORCE_RELOCATION (fixP))
+ 		{
++		  /* (TIGCC 20030717) Zero out add_symbolP only if !TC_FORCE_RELOCATION.
++		                      -- Kevin Kofler  */
++		  add_symbolP = NULL;
++
+ 		  fixP->fx_addsy = NULL;
+ 		  fixP->fx_subsy = NULL;
+ 		  fixP->fx_done = 1;
+@@ -4319,6 +4367,8 @@
+ #endif
+ 		       )
+ 		{
++/* (TIGCC 20030716) Take TC_FORCE_RELOCATION_SUB_LOCAL into account. -- Kevin Kofler  */
++		 if (!TC_FORCE_RELOCATION_SUB_LOCAL (fixP)) {
+ 		  /* Make it pc-relative.  */
+ 		  add_number += (md_pcrel_from (fixP)
+ 				 - S_GET_VALUE (sub_symbolP));
+@@ -4326,15 +4376,19 @@
+ 		  fixP->fx_pcrel = 1;
+ 		  sub_symbolP = 0;
+ 		  fixP->fx_subsy = 0;
++		 }
+ 		}
+ #endif
+ 	      else
+ 		{
++/* (TIGCC 20030716) Take UNDEFINED_DIFFERENCE_OK into account. -- Kevin Kofler  */
++#ifndef UNDEFINED_DIFFERENCE_OK
+ 		  as_bad_where (fixP->fx_file, fixP->fx_line,
+ 				_("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld."),
+ 				segment_name (S_GET_SEGMENT (sub_symbolP)),
+ 				S_GET_NAME (sub_symbolP),
+ 				(long) (fragP->fr_address + where));
++#endif
+ 		}
+ 	    }
+ 	}
+@@ -4473,7 +4527,13 @@
+ 
+       md_apply_fix3 (fixP, (valueT *) & add_number, this_segment_type);
+ 
+-      if (!fixP->fx_bit_fixP && ! fixP->fx_no_overflow)
++/* (TIGCC 20030716) Reuse fx_im_disp to turn off range checking on the 68k.
++                    -- Kevin Kofler  */
++      if (!fixP->fx_bit_fixP && ! fixP->fx_no_overflow
++#ifdef TC_M68K
++          && !fixP->fx_im_disp
++#endif
++      )
+ 	{
+ #ifndef TC_M88K
+ 	  /* The m88k uses the offset field of the reloc to get around
+diff -Naur binutils-2.14.orig/gas/config/obj-coff.h binutils-2.14.tigcc11/gas/config/obj-coff.h
+--- binutils-2.14.orig/gas/config/obj-coff.h	Fri Apr  4 10:15:14 2003
++++ binutils-2.14.tigcc11/gas/config/obj-coff.h	Sun Sep  5 01:33:44 2004
+@@ -477,7 +477,8 @@
+ #define C_DEBUG_SECTION		N_DEBUG
+ #define C_NTV_SECTION		N_TV
+ #define C_PTV_SECTION		P_TV
+-#define C_REGISTER_SECTION	50
++/* (TIGCC 20040905) Don't hardcode number of sections here. -- Kevin Kofler */
++#define C_REGISTER_SECTION	(N_SEGMENTS+10)
+ 
+ /* Macros to extract information from a symbol table entry.
+    This syntaxic indirection allows independence regarding a.out or coff.
+@@ -500,20 +501,31 @@
+ /* Return true for symbols that should not be reduced to section
+    symbols or eliminated from expressions, because they may be
+    overridden by the linker.  */
++/* (TIGCC 20030716) Never reduce or eliminate relocs in all-relocs mode.
++   (TIGCC 20040719) Don't force relocs for absolute symbols if !flag_all_relocs.
++   (TIGCC 20040725) Force relocs for symbols in mergeable sections.
++                    -- Kevin Kofler  */
+ #define S_FORCE_RELOC(s, strict) \
+-  (!SEG_NORMAL (S_GET_SEGMENT (s)) || (strict && S_IS_WEAK (s)))
++  ((!SEG_NORMAL (S_GET_SEGMENT (s)) && S_GET_SEGMENT (s) != absolute_section) \
++   || (strict && S_IS_WEAK (s)) || flag_all_relocs \
++   || (segment_info[S_GET_SEGMENT (s)].scnhdr.s_flags & STYP_MERGEABLE))
+ 
+ /* True if a debug special symbol entry.  */
+ #define S_IS_DEBUG(s) \
+   ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION)
+ 
+ /* True if a symbol is local symbol name.  */
+-/* A symbol name whose name includes ^A is a gas internal pseudo symbol.  */
++/* A symbol name whose name includes ^A is a gas internal pseudo symbol.
++   (TIGCC 20030716) However, we want them output when outputting local symbols.
++   (TIGCC 20040724) Also, we always want to output local symbols in mergeable
++                    sections, because our linker relies on that.
++                    -- Kevin Kofler  */
+ #define S_IS_LOCAL(s) \
+   ((s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION \
+-   || (S_LOCAL_NAME(s) && ! flag_keep_locals && ! S_IS_DEBUG (s)) \
+-   || strchr (S_GET_NAME (s), '\001') != NULL \
+-   || strchr (S_GET_NAME (s), '\002') != NULL \
++   || (S_LOCAL_NAME(s) && ! flag_keep_locals && ! S_IS_DEBUG (s) \
++       && !(segment_info[S_GET_SEGMENT (s)].scnhdr.s_flags & STYP_MERGEABLE)) \
++   || (strchr (S_GET_NAME (s), '\001') != NULL && ! flag_keep_locals) \
++   || (strchr (S_GET_NAME (s), '\002') != NULL && ! flag_keep_locals) \
+    || (flag_strip_local_absolute \
+        && !S_IS_EXTERNAL(s) \
+        && (s)->sy_symbol.ost_entry.n_scnum == C_ABS_SECTION))
+diff -Naur binutils-2.14.orig/gas/config/tc-m68k.c binutils-2.14.tigcc11/gas/config/tc-m68k.c
+--- binutils-2.14.orig/gas/config/tc-m68k.c	Thu Dec 12 22:16:16 2002
++++ binutils-2.14.tigcc11/gas/config/tc-m68k.c	Mon Sep 20 19:08:14 2004
+@@ -75,6 +75,7 @@
+ int flag_want_pic;
+ 
+ static int flag_short_refs;	/* -l option */
++static int flag_short_jumps;	/* --short-jumps option */
+ static int flag_long_jumps;	/* -S option */
+ static int flag_keep_pcrel;	/* --pcrel option.  */
+ 
+@@ -692,15 +693,24 @@
+ tc_coff_fix2rtype (fixP)
+      fixS *fixP;
+ {
++/* (TIGCC 20040920) Handle unoptimizable relocs.  -- Kevin Kofler */
++  short isunopt;
++  isunopt = (fixP->fx_unoptimizable) ? R_UNOPTIMIZABLE : 0;
++
+   if (fixP->fx_tcbit && fixP->fx_size == 4)
+-    return R_RELLONG_NEG;
++    return isunopt | R_RELLONG_NEG;
++/* (TIGCC 20030716) Handle word and byte negative relocs.  -- Kevin Kofler */
++  if (fixP->fx_tcbit && fixP->fx_size == 2)
++    return isunopt | R_RELWORD_NEG;
++  if (fixP->fx_tcbit && fixP->fx_size == 1)
++    return isunopt | R_RELBYTE_NEG;
+ #ifdef NO_PCREL_RELOCS
+   know (fixP->fx_pcrel == 0);
+-  return (fixP->fx_size == 1 ? R_RELBYTE
++  return isunopt | (fixP->fx_size == 1 ? R_RELBYTE
+ 	  : fixP->fx_size == 2 ? R_DIR16
+ 	  : R_DIR32);
+ #else
+-  return (fixP->fx_pcrel ?
++  return isunopt | (fixP->fx_pcrel ?
+ 	  (fixP->fx_size == 1 ? R_PCRBYTE :
+ 	   fixP->fx_size == 2 ? R_PCRWORD :
+ 	   R_PCRLONG) :
+@@ -2574,8 +2584,15 @@
+ 		    the_ins.opcode[0] = 0x4EB9;
+ 		  else					/* jCC */
+ 		    {
++		      /* (TIGCC 20030902) Add a PC-relative reloc (unconditionally, because
++		                          it will be removed later on if not in all-relocs
++		                          mode). -- Kevin Kofler  */
++		      struct m68k_exp temp_expr = {SIZE_UNSPEC,
++		      {symbol_new (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix () + 8, frag_now),
++		      NULL, 0, O_symbol, 0, 0}};
+ 		      the_ins.opcode[0] ^= 0x0100;
+ 		      the_ins.opcode[0] |= 0x0006;
++		      add_fix ('B' /*case-sensitive!*/, &temp_expr, 1 /*PCREL*/, -1 /*PCREL fix for bytes*/);
+ 		      addword (0x4EF9);
+ 		    }
+ 		  add_fix ('l', &opP->disp, 0, 0);
+@@ -3659,6 +3676,12 @@
+ 			      get_reloc_code (n, the_ins.reloc[m].pcrel,
+ 					      the_ins.reloc[m].pic_reloc));
+ 	  fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
++	  /* (TIGCC 20040920) Only source operands are optimizable. However, we have
++	     to account for an ugly special case: jbcc pseudo-opcodes, which are
++	     actually 2 instructions. -- Kevin Kofler */
++	  if ((the_ins.reloc[m].n > 4) || (the_ins.reloc[m].n == 3)
++	      || ((the_ins.reloc[m].n == 4) && ((the_ins.opcode[0]&0xf000) != 0x6000)))
++	    fixP->fx_unoptimizable = 1;
+ 	  if (the_ins.reloc[m].wid == 'B')
+ 	    fixP->fx_signed = 1;
+ 	}
+@@ -3721,6 +3744,12 @@
+ 			      get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ 					      the_ins.reloc[m].pic_reloc));
+ 	  fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
++	  /* (TIGCC 20040920) Only source operands are optimizable. However, we have
++	     to account for an ugly special case: jbcc pseudo-opcodes, which are
++	     actually 2 instructions. -- Kevin Kofler */
++	  if ((the_ins.reloc[m].n > 4) || (the_ins.reloc[m].n == 3)
++	      || ((the_ins.reloc[m].n == 4) && ((the_ins.opcode[0]&0xf000) != 0x6000)))
++	    fixP->fx_unoptimizable = 1;
+ 	}
+       (void) frag_var (rs_machine_dependent, 10, 0,
+ 		       (relax_substateT) (the_ins.fragb[n].fragty),
+@@ -3758,6 +3787,12 @@
+ 			  get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ 					  the_ins.reloc[m].pic_reloc));
+       fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
++      /* (TIGCC 20040920) Only source operands are optimizable. However, we have
++         to account for an ugly special case: jbcc pseudo-opcodes, which are
++         actually 2 instructions. -- Kevin Kofler */
++      if ((the_ins.reloc[m].n > 4) || (the_ins.reloc[m].n == 3)
++          || ((the_ins.reloc[m].n == 4) && ((the_ins.opcode[0]&0xf000) != 0x6000)))
++        fixP->fx_unoptimizable = 1;
+     }
+ }
+ 
+@@ -4241,7 +4276,9 @@
+ 
+   val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ 
+-  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
++/* (TIGCC 20030716) We aren't done when we still have something to subtract.
++                    -- Kevin Kofler  */
++  if (fixP->fx_addsy == NULL && fixP->fx_subsy == NULL && fixP->fx_pcrel == 0)
+     fixP->fx_done = 1;
+ 
+ #ifdef OBJ_ELF
+@@ -4264,6 +4301,55 @@
+     return;
+ #endif
+ 
++  /* Fix up a negative reloc.  */
++  if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
++    {
++      fixP->fx_addsy = fixP->fx_subsy;
++      fixP->fx_subsy = NULL;
++      fixP->fx_tcbit = 1;
++      val = -val; /* (TIGCC 20030716) */
++    }
++  /* (TIGCC 20030716) Fix up an address difference by splitting it into its
++                      components.
++                      Fix up subtraction of the dot symbol by changing the reloc
++                      to PC-relative (disabled 20030717).  -- Kevin Kofler
++     (TIGCC 20040807) For common symbols, the value is the size, not the
++                      position, so don't use it.  -- Kevin Kofler  */
++  else if (fixP->fx_addsy != NULL && fixP->fx_subsy != NULL)
++    {
++#if 0 /* (TIGCC 20030717) This is unnecessary (see expr.c fix) and probably wrong. */
++      if (!~fixP->fx_subsy->sy_number) { /* detect the dot symbol */
++        /* make the reloc PC-relative: */
++        val += md_pcrel_from (fixP);
++        fixP->fx_offset = *valP = val;
++        fixP->fx_pcrel = 1;
++        fixP->fx_subsy = NULL;
++      } else {
++#endif
++        fixS *negreloc = fix_new (fixP->fx_frag, fixP->fx_where, fixP->fx_size,
++                                  fixP->fx_subsy, fixP->fx_offset
++                                                  + (S_IS_COMMON (fixP->fx_addsy) ? 0 : S_GET_VALUE (fixP->fx_addsy))
++                                                  + segment_info[S_GET_SEGMENT (fixP->fx_addsy)].scnhdr.s_paddr
++                                                  - (((S_IS_COMMON (fixP->fx_subsy) ? 0 : S_GET_VALUE (fixP->fx_subsy))
++                                                     + segment_info[S_GET_SEGMENT (fixP->fx_subsy)].scnhdr.s_paddr)
++                                                     << 1) /* (TIGCC 20030717) Yes, we need to subtract this twice!
++                                                               This kludge compensates for later incorrect
++                                                               computations in obj-coff.c. -- Kevin Kofler  */,
++                                  0, 0);
++        if (negreloc) {
++          fixP->fx_offset = 0; /* We have transferred the offset to the negative reloc.  */
++          fixP->fx_pcrel = 0;
++          fixP->fx_subsy = NULL;
++          negreloc->fx_tcbit = 1;
++          /* turn off range checking for both relocs: */
++          fixP->fx_im_disp = negreloc->fx_im_disp = 1;
++        }
++#if 0
++      }
++#endif
++    }
++
++  /* (TIGCC 20030716) Moved this down so val can be adjusted. -- Kevin Kofler  */
+   switch (fixP->fx_size)
+     {
+       /* The cast to offsetT below are necessary to make code
+@@ -4291,13 +4377,8 @@
+       BAD_CASE (fixP->fx_size);
+     }
+ 
+-  /* Fix up a negative reloc.  */
+-  if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
+-    {
+-      fixP->fx_addsy = fixP->fx_subsy;
+-      fixP->fx_subsy = NULL;
+-      fixP->fx_tcbit = 1;
+-    }
++  /* (TIGCC 20030716) Reuse fx_im_disp to turn off range checking. -- Kevin Kofler  */
++  if (fixP->fx_im_disp) return;
+ 
+   /* For non-pc-relative values, it's conceivable we might get something
+      like "0xff" for a byte field.  So extend the upper part of the range
+@@ -4412,6 +4493,27 @@
+       fragP->fr_opcode[0] ^= 0x01;	/* invert bcc */
+       fragP->fr_opcode[1] = 0x6;/* branch offset = 6 */
+ 
++      /* (TIGCC 20030902) Add a PC-relative reloc (unconditionally, because
++                          it will be removed later on if not in all-relocs
++                          mode).  -- Kevin Kofler
++         (TIGCC 20030908) Unfortunately, we cannot create symbols here for some
++                          reason, so we create the symbol in advance in
++                          md_estimate_size_before_relax and store it into the
++                          frag structure of the next frag. Here, we only have to
++                          read it.  -- Kevin Kofler, patch by Sebastian Reichelt
++         */
++      {
++	fragS *nextFragP = fragP->fr_next;
++	symbolS *symbolP = NULL;
++	if (nextFragP)
++	  symbolP = nextFragP->fr_start_symbol;
++
++	if (symbolP)
++	  fix_new (fragP, fragP->fr_fix - 1, 1, symbolP, -1, 1, RELAX_RELOC_PC8);
++	else
++	  as_warn_where (fragP->fr_file, fragP->fr_line, _("no symbol available for pseudo-op code"));
++      }
++
+       /* JF: these used to be fr_opcode[2,3], but they may be in a
+ 	   different frag, in which case refering to them is a no-no.
+ 	   Only fr_opcode[0,1] are guaranteed to work.  */
+@@ -4578,8 +4680,17 @@
+ 	    && relaxable_symbol (fragP->fr_symbol))
+ 	  {
+ 	    fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
++	    /* (TIGCC 20030909) Create a symbol at the beginning of the next frag
++	                        and store it into the frag structure, because
++	                        md_convert_frag_1 might need a symbol there, but
++	                        can't create it itself. This is necessary only for
++	                        conditional jumps. -- Kevin Kofler  */
++	    if ((TABTYPE (fragP->fr_subtype) == BRABSJCOND) && fragP->fr_next)
++	      {
++		fragP->fr_next->fr_start_symbol = symbol_new (FAKE_LABEL_NAME, segment, fragP->fr_next->fr_address, fragP->fr_next);
++	      }
+ 	  }
+-	else if (flag_short_refs)
++	else if (flag_short_jumps)
+ 	  {
+ 	    /* Symbol is undefined and we want short ref.  */
+ 	    fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
+@@ -4588,6 +4699,17 @@
+ 	  {
+ 	    /* Symbol is still undefined.  Make it LONG.  */
+ 	    fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), LONG);
++	    /* (TIGCC 20030908) Create a symbol at the beginning of the next frag
++	                        and store it into the frag structure, because
++	                        md_convert_frag_1 might need a symbol there, but
++	                        can't create it itself.
++	                        -- Kevin Kofler, patch by Sebastian Reichelt
++	       (TIGCC 20030909) This is necessary only for conditional jumps.
++	                        -- Kevin Kofler  */
++	    if ((TABTYPE (fragP->fr_subtype) == BRABSJCOND) && fragP->fr_next)
++	      {
++		fragP->fr_next->fr_start_symbol = symbol_new (FAKE_LABEL_NAME, segment, fragP->fr_next->fr_address, fragP->fr_next);
++	      }
+ 	  }
+ 	break;
+       }
+@@ -4614,7 +4736,7 @@
+       {
+ 	if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ 	     && relaxable_symbol (fragP->fr_symbol))
+-	    || flag_short_refs)
++	    || flag_short_jumps)
+ 	  {
+ 	    fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
+ 	  }
+@@ -4640,7 +4762,8 @@
+     case TAB (ABSTOPCREL, SZ_UNDEF):
+       {
+ 	if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+-	     && relaxable_symbol (fragP->fr_symbol)))
++	     && relaxable_symbol (fragP->fr_symbol))
++	    || flag_short_refs)
+ 	  {
+ 	    fragP->fr_subtype = TAB (ABSTOPCREL, SHORT);
+ 	  }
+@@ -4684,6 +4807,7 @@
+ 	    }
+ 	}
+       break;
++
+     default:
+       break;
+     }
+@@ -6753,6 +6877,8 @@
+   {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
+ #define OPTION_PCREL (OPTION_MD_BASE + 7)
+   {"pcrel", no_argument, NULL, OPTION_PCREL},
++#define OPTION_SHORT_JUMPS (OPTION_MD_BASE + 8)
++  {"short-jumps", no_argument, NULL, OPTION_SHORT_JUMPS},
+   {NULL, no_argument, NULL, 0}
+ };
+ size_t md_longopts_size = sizeof (md_longopts);
+@@ -6767,6 +6893,12 @@
+     case 'l':			/* -l means keep external to 2 bit offset
+ 				   rather than 16 bit one */
+       flag_short_refs = 1;
++      flag_short_jumps = 1;
++      break;
++
++    case OPTION_SHORT_JUMPS:	/* --short-jumps is like -l only for
++				   jumps.  */
++      flag_short_jumps = 1;
+       break;
+ 
+     case 'S':			/* -S means that jbsr's always turn into
+@@ -6946,6 +7078,7 @@
+   fprintf (stream, _("\
+ 680X0 options:\n\
+ -l			use 1 word for refs to undefined symbols [default 2]\n\
++--short-jumps		use 1 word for jumps to undefined symbols [default 2]\n\
+ -m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060 |\n\
+ -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -m68360 | -mcpu32 |\n\
+ -m5200  | -m5202  | -m5204  | -m5206  | -m5206e | -m5307  | -m5407\n\
+diff -Naur binutils-2.14.orig/gas/config/tc-m68k.h binutils-2.14.tigcc11/gas/config/tc-m68k.h
+--- binutils-2.14.orig/gas/config/tc-m68k.h	Thu Jan 23 12:51:04 2003
++++ binutils-2.14.tigcc11/gas/config/tc-m68k.h	Wed Jul 16 11:48:34 2003
+@@ -220,3 +220,19 @@
+   while (0)
+ 
+ #define DWARF2_LINE_MIN_INSN_LENGTH 2
++
++/* (TIGCC 20030716) Allow difference of undefined symbols. -- Kevin Kofler  */
++#define UNDEFINED_DIFFERENCE_OK
++
++/* (TIGCC 20030716) Force relocs in all-relocs mode. -- Kevin Kofler  */
++#define TC_FORCE_RELOCATION(FIX)		\
++  (generic_force_reloc (FIX))
++#define TC_FORCE_RELOCATION_ABS(FIX)		\
++  (0)
++#define TC_FORCE_RELOCATION_LOCAL(FIX)		\
++  (TC_FORCE_RELOCATION (FIX))
++#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG)	\
++  (! SEG_NORMAL (SEG) || TC_FORCE_RELOCATION (FIX))
++#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX)	\
++  (TC_FORCE_RELOCATION (FIX))
++/* (END TIGCC 20030716) */
+diff -Naur binutils-2.14.orig/gas/expr.c binutils-2.14.tigcc11/gas/expr.c
+--- binutils-2.14.orig/gas/expr.c	Fri Oct 18 03:56:38 2002
++++ binutils-2.14.tigcc11/gas/expr.c	Mon Jul 19 07:23:24 2004
+@@ -1740,8 +1740,11 @@
+ 	  /* X + constant.  */
+ 	  resultP->X_add_number += right.X_add_number;
+ 	}
+-      /* This case comes up in PIC code.  */
+-      else if (op_left == O_subtract
++      /* This case comes up in PIC code.
++         (TIGCC 20040719) This optimization isn't valid in all-relocs mode.
++                          -- Kevin Kofler  */
++      else if (!flag_all_relocs
++	       && op_left == O_subtract
+ 	       && right.X_op == O_symbol
+ 	       && resultP->X_op == O_symbol
+ 	       && (symbol_get_frag (right.X_add_symbol)
+@@ -1837,6 +1840,15 @@
+ 		       && right.X_add_number == 0)))
+ 	{
+ 	  /* Symbol OP symbol.  */
++
++	  /* (TIGCC 20030717) Optimize .set sym2,sym3+c; sym1-sym2 to
++	     .set sym2,sym3+c; sym1-(sym3+c). The code below will further change
++	     this to .set sym2,sym3+c; (sym1-c)-sym3. -- Kevin Kofler  */
++	  if (!right.X_add_number && right.X_add_symbol->sy_value.X_op == O_symbol) {
++	    resolve_symbol_value(right.X_add_symbol);
++	    memcpy(&right, &right.X_add_symbol->sy_value, sizeof(expressionS));
++	  }
++
+ 	  resultP->X_op = op_left;
+ 	  resultP->X_op_symbol = right.X_add_symbol;
+ 	  if (op_left == O_add)
+diff -Naur binutils-2.14.orig/gas/frags.h binutils-2.14.tigcc11/gas/frags.h
+--- binutils-2.14.orig/gas/frags.h	Fri May  3 04:25:32 2002
++++ binutils-2.14.tigcc11/gas/frags.h	Mon Sep  8 23:25:34 2003
+@@ -66,6 +66,9 @@
+   char *fr_file;
+   unsigned int fr_line;
+ 
++  /* (TIGCC) Symbol at the beginning of the frag. May be NULL.  */
++  symbolS *fr_start_symbol;
++
+ #ifndef NO_LISTING
+   struct list_info_struct *line;
+ #endif
+diff -Naur binutils-2.14.orig/gas/listing.c binutils-2.14.tigcc11/gas/listing.c
+--- binutils-2.14.orig/gas/listing.c	Wed Jun 26 03:18:42 2002
++++ binutils-2.14.tigcc11/gas/listing.c	Mon Sep  1 23:26:54 2003
+@@ -976,7 +976,8 @@
+   int show_listing = 1;
+   unsigned int width;
+ 
+-  buffer = xmalloc (listing_rhs_width);
++  buffer = xmalloc (listing_rhs_width + 1); /* (TIGCC 20030901) Add 1 for the
++    terminating '\0' character. -- Kevin Kofler  */
+   data_buffer = xmalloc (MAX_BYTES);
+   eject = 1;
+   list = head;
+@@ -995,8 +996,8 @@
+     {
+       unsigned int list_line;
+ 
+-      width = listing_rhs_width > paper_width ? paper_width :
+-	listing_rhs_width;
++      width = (listing_rhs_width > paper_width ? paper_width :
++	listing_rhs_width) + 1; /* (TIGCC 20030901) See above.  */
+ 
+       list_line = list->line;
+       switch (list->edict)
+diff -Naur binutils-2.14.orig/gas/read.c binutils-2.14.tigcc11/gas/read.c
+--- binutils-2.14.orig/gas/read.c	Mon Jun  2 22:35:22 2003
++++ binutils-2.14.tigcc11/gas/read.c	Mon Sep 20 17:38:38 2004
+@@ -3759,8 +3759,9 @@
+ #define TC_CONS_RELOC 0
+ #endif
+ #endif
++      /* (TIGCC 20040920) Constants aren't optimizable relocs. -- Kevin Kofler */
+       fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
+-		   TC_CONS_RELOC);
++		   TC_CONS_RELOC) -> fx_unoptimizable = 1;
+ #endif /* TC_CONS_FIX_NEW */
+ #endif /* BFD_ASSEMBLER */
+     }
+diff -Naur binutils-2.14.orig/gas/subsegs.c binutils-2.14.tigcc11/gas/subsegs.c
+--- binutils-2.14.orig/gas/subsegs.c	Sun Dec  8 03:47:56 2002
++++ binutils-2.14.tigcc11/gas/subsegs.c	Sun Sep  5 01:53:14 2004
+@@ -41,6 +41,8 @@
+ 
+ #endif /* MANY_SEGMENTS */
+ char const *const seg_name[] = {
++/* (TIGCC 20040905) Allow arbitrary number of sections here. -- Kevin Kofler */
++#if 0
+   "absolute",
+ #ifdef MANY_SEGMENTS
+   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
+@@ -52,6 +54,7 @@
+   "data",
+   "bss",
+ #endif /* MANY_SEGMENTS */
++#endif /* 0 */
+   "unknown",
+   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
+   "expr",
+@@ -61,6 +64,17 @@
+   "register",
+   "",
+ };				/* Used by error reporters, dumpers etc.  */
++
++char *segment_name (n) int n;
++{
++  if (!n) return "absolute";
++  else if (SEG_NORMAL(n)) {
++    static char s[8];
++    sprintf(s,"e%d",n-SEG_E0);
++    return s;
++  } else return seg_name[n-(N_SEGMENTS+1)];
++}
++
+ #else /* BFD_ASSEMBLER */
+ 
+ /* Gas segment information for bfd_abs_section_ptr and
+diff -Naur binutils-2.14.orig/gas/symbols.c binutils-2.14.tigcc11/gas/symbols.c
+--- binutils-2.14.orig/gas/symbols.c	Fri Jan 24 01:12:30 2003
++++ binutils-2.14.tigcc11/gas/symbols.c	Mon Jul 19 18:02:20 2004
+@@ -1155,6 +1155,14 @@
+ 		       || add_symbol == op_symbol)))
+ 	    report_op_error (symp, add_symbol, op_symbol);
+ 
++	  /* (TIGCC 20040719) In all-relocs mode, we can't apply operations other
++	                      than + or - on an address or address difference.
++	                      -- Kevin Kofler */
++	  if (flag_all_relocs && finalize_syms
++	      && !(op == O_subtract || op == O_add)
++	      && final_seg == undefined_section)
++	    report_op_error (symp, add_symbol, op_symbol);
++
+ 	  if (final_seg == expr_section || final_seg == undefined_section)
+ 	    final_seg = absolute_section;
+ 
+diff -Naur binutils-2.14.orig/gas/symbols.h binutils-2.14.tigcc11/gas/symbols.h
+--- binutils-2.14.orig/gas/symbols.h	Thu Jan 23 12:51:04 2003
++++ binutils-2.14.tigcc11/gas/symbols.h	Sun Sep  5 01:14:02 2004
+@@ -138,11 +138,16 @@
+ /*
+  * Current means for getting from symbols to segments and vice verse.
+  * This will change for infinite-segments support (e.g. COFF).
++ * (TIGCC 20040905) And indeed it does. -- Kevin Kofler
+  */
+ extern const segT N_TYPE_seg[];	/* subseg.c */
+ 
++#if 0
+ #define	SEGMENT_TO_SYMBOL_TYPE(seg)  ( seg_N_TYPE [(int) (seg)] )
+ extern const short seg_N_TYPE[];/* subseg.c */
++#else
++short SEGMENT_TO_SYMBOL_TYPE PARAMS ((int seg));
++#endif
+ 
+ #define	N_REGISTER	30	/* Fake N_TYPE value for SEG_REGISTER */
+ 
+diff -Naur binutils-2.14.orig/gas/write.c binutils-2.14.tigcc11/gas/write.c
+--- binutils-2.14.orig/gas/write.c	Mon Apr  7 05:54:00 2003
++++ binutils-2.14.tigcc11/gas/write.c	Mon Sep 20 17:20:00 2004
+@@ -224,6 +224,7 @@
+ #if defined(NEED_FX_R_TYPE) || defined (BFD_ASSEMBLER)
+   fixP->fx_r_type = r_type;
+ #endif
++  fixP->fx_unoptimizable = 0; /* (TIGCC 20040920) */
+   fixP->fx_im_disp = 0;
+   fixP->fx_pcrel_adjust = 0;
+   fixP->fx_bit_fixP = 0;
+@@ -863,6 +864,11 @@
+ 	    continue;
+ 	  }
+ 
++	/* (TIGCC 20030716) Only reduce relocs which refer to local symbols we
++	                    aren't going to output. -- Kevin Kofler  */
++	if (! S_IS_LOCAL (sym))
++		continue;
++
+ 	/* Don't try to reduce relocs which refer to non-local symbols
+            in .linkonce sections.  It can lead to confusion when a
+            debugging section refers to a .linkonce section.  I hope
+@@ -1419,7 +1425,7 @@
+       /* This now gets called even if we had errors.  In that case,
+          any alignment is meaningless, and, moreover, will look weird
+          if we are generating a listing.  */
+-      if (!had_errors ())
++      if (0 /*!had_errors ()*/)
+ 	{
+ 	  alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
+ #ifdef BFD_ASSEMBLER
+diff -Naur binutils-2.14.orig/gas/write.h binutils-2.14.tigcc11/gas/write.h
+--- binutils-2.14.orig/gas/write.h	Fri Sep 20 01:51:34 2002
++++ binutils-2.14.tigcc11/gas/write.h	Mon Sep 20 17:16:44 2004
+@@ -69,9 +69,12 @@
+      look into it for version 2.6.  */
+   unsigned fx_plt : 1;
+ 
++  /* (TIGCC 20040920) Is this an unoptimizable reloc? -- Kevin Kofler  */
++  unsigned fx_unoptimizable : 1;
++
+   /* Is this value an immediate displacement?  */
+   /* Only used on i960 and ns32k; merge it into TC_FIX_TYPE sometime.  */
+-  unsigned fx_im_disp : 2;
++  unsigned fx_im_disp : 1;
+ 
+   /* A bit for the CPU specific code.
+      This probably can be folded into tc_fix_data, below.  */
+diff -Naur binutils-2.14.orig/include/coff/internal.h binutils-2.14.tigcc11/include/coff/internal.h
+--- binutils-2.14.orig/include/coff/internal.h	Wed Aug 28 12:38:48 2002
++++ binutils-2.14.tigcc11/include/coff/internal.h	Mon Sep 20 17:30:42 2004
+@@ -345,6 +345,9 @@
+ 
+ #define STYP_LIT	0x8020	/* Literal data (like STYP_TEXT) */
+ 
++/* (TIGCC 20040724) TIGCC COFF extensions for section flags -- Kevin Kofler */
++#define STYP_MERGEABLE 0x1000000
++#define STYP_UNALIGNED 0x2000000
+ 
+ /********************** LINE NUMBERS **********************/
+ 
+@@ -737,5 +740,10 @@
+ #define R_W65_PCR16	9
+ 
+ #define R_W65_DP       10  /* direct page 8 bits only   */
++
++/* (TIGCC 20030716, 20040920) TIGCC COFF extensions -- Kevin Kofler  */
++#define R_RELWORD_NEG 0x7161
++#define R_RELBYTE_NEG 0x7162
++#define R_UNOPTIMIZABLE 0x8000
+ 
+ #endif /* GNU_COFF_INTERNAL_H */
+diff -Naur binutils-2.14.orig/opcodes/configure binutils-2.14.tigcc11/opcodes/configure
+--- binutils-2.14.orig/opcodes/configure	Mon Jun  2 22:35:16 2003
++++ binutils-2.14.tigcc11/opcodes/configure	Sat Jul 12 09:36:42 2003
+@@ -487,7 +487,7 @@
+ 
+ # A filename unique to this package, relative to the directory that
+ # configure is in, which we can look for to find out if srcdir is correct.
+-ac_unique_file=z8k-dis.c
++ac_unique_file=m68k-dis.c
+ 
+ # Find the source files, if location was not specified.
+ if test -z "$srcdir"; then
+diff -Naur binutils-2.14.orig/opcodes/configure.in binutils-2.14.tigcc11/opcodes/configure.in
+--- binutils-2.14.orig/opcodes/configure.in	Mon Jun  2 22:35:16 2003
++++ binutils-2.14.tigcc11/opcodes/configure.in	Sat Jul 12 09:36:42 2003
+@@ -2,7 +2,7 @@
+ dnl
+ 
+ AC_PREREQ(2.13)
+-AC_INIT(z8k-dis.c)
++AC_INIT(m68k-dis.c)
+ 
+ AC_CANONICAL_SYSTEM
+ AC_ISC_POSIX
+diff -Naur binutils-2.14.orig/opcodes/m68k-opc.c binutils-2.14.tigcc11/opcodes/m68k-opc.c
+--- binutils-2.14.orig/opcodes/m68k-opc.c	Mon Nov 12 16:36:06 2001
++++ binutils-2.14.tigcc11/opcodes/m68k-opc.c	Mon Sep  1 23:12:36 2003
+@@ -251,6 +251,7 @@
+ 
+ {"clrb",	one(0041000),	one(0177700), "$s", m68000up | mcf },
+ {"clrw",	one(0041100),	one(0177700), "$s", m68000up | mcf },
++{"clrl",	one(0070000),	one(0170477), "Dd", m68000 },
+ {"clrl",	one(0041200),	one(0177700), "$s", m68000up | mcf },
+ 
+ {"cmp2b",	two(0000300,0), two(0177700,07777), "!sR1", m68020up | cpu32 },
+@@ -260,11 +261,11 @@
+ {"cmpaw",	one(0130300),	one(0170700), "*wAd", m68000up },
+ {"cmpal",	one(0130700),	one(0170700), "*lAd", m68000up | mcf },
+ 
+-{"cmpib",	one(0006000),	one(0177700), "#b@s", m68000up },
++{"cmpib",	one(0006000),	one(0177700), "#b$s", m68000up },
+ {"cmpib",	one(0006000),	one(0177700), "#bDs", mcf5407 },
+-{"cmpiw",	one(0006100),	one(0177700), "#w@s", m68000up },
++{"cmpiw",	one(0006100),	one(0177700), "#w$s", m68000up },
+ {"cmpiw",	one(0006100),	one(0177700), "#wDs", mcf5407 },
+-{"cmpil",	one(0006200),	one(0177700), "#l@s", m68000up },
++{"cmpil",	one(0006200),	one(0177700), "#l$s", m68000up },
+ {"cmpil",	one(0006200),	one(0177700), "#lDs", mcf },
+ 
+ {"cmpmb",	one(0130410),	one(0170770), "+s+d", m68000up },
+@@ -272,18 +273,18 @@
+ {"cmpml",	one(0130610),	one(0170770), "+s+d", m68000up },
+ 
+ /* The cmp opcode can generate the cmpa, cmpm, and cmpi instructions.  */
+-{"cmpb",	one(0006000),	one(0177700), "#b@s", m68000up },
++{"cmpb",	one(0006000),	one(0177700), "#b$s", m68000up },
+ {"cmpb",	one(0006000),	one(0177700), "#bDs", mcf5407 },
+ {"cmpb",	one(0130410),	one(0170770), "+s+d", m68000up },
+ {"cmpb",	one(0130000),	one(0170700), ";bDd", m68000up },
+ {"cmpb",	one(0130000),	one(0170700), "*bDd", mcf5407 },
+ {"cmpw",	one(0130300),	one(0170700), "*wAd", m68000up },
+-{"cmpw",	one(0006100),	one(0177700), "#w@s", m68000up },
++{"cmpw",	one(0006100),	one(0177700), "#w$s", m68000up },
+ {"cmpw",	one(0006100),	one(0177700), "#wDs", mcf5407 },
+ {"cmpw",	one(0130510),	one(0170770), "+s+d", m68000up },
+ {"cmpw",	one(0130100),	one(0170700), "*wDd", m68000up | mcf5407 },
+ {"cmpl",	one(0130700),	one(0170700), "*lAd", m68000up | mcf },
+-{"cmpl",	one(0006200),	one(0177700), "#l@s", m68000up },
++{"cmpl",	one(0006200),	one(0177700), "#l$s", m68000up },
+ {"cmpl",	one(0006200),	one(0177700), "#lDs", mcf },
+ {"cmpl",	one(0130610),	one(0170770), "+s+d", m68000up },
+ {"cmpl",	one(0130200),	one(0170700), "*lDd", m68000up | mcf },
+@@ -1970,6 +1971,7 @@
+ 
+ const struct m68k_opcode_alias m68k_opcode_aliases[] =
+ {
++  { "abcdb",	"abcd", }, /* (TIGCC 20030901) */
+   { "add",	"addw", },
+   { "adda",	"addaw", },
+   { "addi",	"addiw", },
+@@ -2068,6 +2070,7 @@
+   { "tdivsl",	"divsl", },
+   { "divs",	"divsw", },
+   { "divu",	"divuw", },
++  { "exgl",	"exg", }, /* (TIGCC 20020512, 20030901) */
+   { "ext",	"extw", },
+   { "extbw",	"extw", },
+   { "extwl",	"extl", },

+ 7225 - 0
tigcc/gcc/gcc-3.3.3-tigcc-8.diff

@@ -0,0 +1,7225 @@
+diff -Naur gcc-3.3.3.orig/gcc/attribs.c gcc-3.3.3.tigcc8/gcc/attribs.c
+--- gcc-3.3.3.orig/gcc/attribs.c	Mon Aug  5 20:46:32 2002
++++ gcc-3.3.3.tigcc8/gcc/attribs.c	Thu Feb 19 21:20:00 2004
+@@ -231,7 +231,54 @@
+ 		  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
+ 	    {
+ 	      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+-		*anode = build_type_copy (*anode);
++	      {
++/* (TIGCC) Neither build_type_copy nor build_type_attribute_variant are
++           applicable here, so we use a slightly modified version of the code in
++           build_type_attribute_variant.
++           The FSF GCC source uses build_type_copy, but that causes attributes
++           to function pointers to simply get lost! */
++
++	        unsigned int hashcode;
++	        tree ntype;
++
++	        ntype = copy_node (*anode);
++
++	        TYPE_POINTER_TO (ntype) = 0;
++	        TYPE_REFERENCE_TO (ntype) = 0;
++
++	        /* Create a new main variant of TYPE.  */
++	        TYPE_MAIN_VARIANT (ntype) = ntype;
++	        TYPE_NEXT_VARIANT (ntype) = 0;
++	        TYPE_READONLY (ntype) = 0;
++	        TYPE_VOLATILE (ntype) = 0;
++	        TYPE_RESTRICT (ntype) = 0;
++
++	        hashcode = (TYPE_HASH (TREE_CODE (ntype))
++	          + TYPE_HASH (TREE_TYPE (ntype))
++	          + attribute_hash_list (TYPE_ATTRIBUTES (ntype)));
++
++	        switch (TREE_CODE (ntype))
++	        {
++	          case FUNCTION_TYPE:
++	            hashcode += TYPE_HASH (TYPE_ARG_TYPES (ntype));
++	            break;
++	          case ARRAY_TYPE:
++	            hashcode += TYPE_HASH (TYPE_DOMAIN (ntype));
++	            break;
++	          case INTEGER_TYPE:
++	            hashcode += TYPE_HASH (TYPE_MAX_VALUE (ntype));
++	            break;
++	          case REAL_TYPE:
++	            hashcode += TYPE_HASH (TYPE_PRECISION (ntype));
++	            break;
++	          default:
++	            break;
++	        }
++
++	        ntype = type_hash_canon (hashcode, ntype);
++	        *anode = build_qualified_type (ntype, TYPE_QUALS (*anode));
++/* (END TIGCC) */
++	      }
+ 	      anode = &TREE_TYPE (*anode);
+ 	    }
+ 	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+diff -Naur gcc-3.3.3.orig/gcc/bb-reorder.c gcc-3.3.3.tigcc8/gcc/bb-reorder.c
+--- gcc-3.3.3.orig/gcc/bb-reorder.c	Fri Mar 21 23:56:58 2003
++++ gcc-3.3.3.tigcc8/gcc/bb-reorder.c	Thu Feb 19 21:20:00 2004
+@@ -95,7 +95,9 @@
+ /* Local function prototypes.  */
+ static void make_reorder_chain		PARAMS ((void));
+ static basic_block make_reorder_chain_1	PARAMS ((basic_block, basic_block));
++#if 0 /* (TIGCC 20030607) See below. */
+ static basic_block maybe_duplicate_computed_goto_succ PARAMS ((basic_block));
++#endif /* 0 */
+ 
+ /* Compute an ordering for a subgraph beginning with block BB.  Record the
+    ordering in RBI()->index and chained through RBI()->next.  */
+@@ -132,6 +134,23 @@
+   RBI (prev)->next = NULL;
+ }
+ 
++#if 0 /* (TIGCC 20030607) Revert the following patch:
++
++2003-03-21  Richard Henderson  <rth@redhat.com>
++
++	PR opt/2001
++	* bb-reorder.c (maybe_duplicate_computed_goto_succ): New.
++	(make_reorder_chain_1): Call it.
++
++	* function.h (struct function): Add computed_goto_common_label,
++	computed_goto_common_reg.
++	* function.c (free_after_compilation): Zap them.
++	* stmt.c (expand_computed_goto): Use them to produce one
++	indirect branch per function.
++
++because it breaks ER_throw, whereas PR opt/2001 is a compilation slowness
++problem (in an extreme case) only.  -- Kevin Kofler  */
++
+ /* If the successor is our artificial computed_jump block, duplicate it.  */
+ 
+ static inline basic_block
+@@ -170,6 +189,7 @@
+ 
+   return NULL;
+ }
++#endif /* 0 */
+ 
+ /* A helper function for make_reorder_chain.
+ 
+@@ -247,9 +267,11 @@
+       next = ((taken && e_taken) ? e_taken : e_fall)->dest;
+     }
+ 
++#if 0 /* (TIGCC 20030607) See above. */
+   /* If the successor is our artificial computed_jump block, duplicate it.  */
+   else
+     next = maybe_duplicate_computed_goto_succ (bb);
++#endif /* 0 */
+ 
+   /* In the absence of a prediction, disturb things as little as possible
+      by selecting the old "next" block from the list of successors.  If
+diff -Naur gcc-3.3.3.orig/gcc/builtin-attrs.def gcc-3.3.3.tigcc8/gcc/builtin-attrs.def
+--- gcc-3.3.3.orig/gcc/builtin-attrs.def	Tue Mar  4 14:37:20 2003
++++ gcc-3.3.3.tigcc8/gcc/builtin-attrs.def	Thu Feb 19 21:20:00 2004
+@@ -63,6 +63,7 @@
+ DEF_ATTR_FOR_INT (2)
+ DEF_ATTR_FOR_INT (3)
+ DEF_ATTR_FOR_INT (4)
++DEF_ATTR_FOR_INT (5)
+ #undef DEF_ATTR_FOR_INT
+ 
+ /* Construct a tree for a list of two integers.  */
+@@ -75,6 +76,8 @@
+ DEF_LIST_INT_INT (2,3)
+ DEF_LIST_INT_INT (3,0)
+ DEF_LIST_INT_INT (3,4)
++DEF_LIST_INT_INT (4,0)
++DEF_LIST_INT_INT (4,5)
+ #undef DEF_LIST_INT_INT
+ 
+ /* Construct tress for identifiers.  */
+@@ -108,6 +111,8 @@
+ 			ATTR_NOTHROW_LIST)
+ DEF_ATTR_TREE_LIST (ATTR_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, \
+ 			ATTR_NOTHROW_LIST)
++DEF_ATTR_TREE_LIST (ATTR_NONNULL_4, ATTR_NONNULL, ATTR_LIST_4, \
++			ATTR_NOTHROW_LIST)
+ 
+ /* Construct a tree for a format attribute.  */
+ #define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES)				 \
+@@ -125,6 +130,10 @@
+ DEF_FORMAT_ATTRIBUTE(SCANF,1,1_2)
+ DEF_FORMAT_ATTRIBUTE(SCANF,2,2_0)
+ DEF_FORMAT_ATTRIBUTE(SCANF,2,2_3)
++DEF_FORMAT_ATTRIBUTE(SCANF,3,3_0)
++DEF_FORMAT_ATTRIBUTE(SCANF,3,3_4)
++DEF_FORMAT_ATTRIBUTE(SCANF,4,4_0)
++DEF_FORMAT_ATTRIBUTE(SCANF,4,4_5)
+ DEF_FORMAT_ATTRIBUTE(STRFTIME,3,3_0)
+ DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4)
+ #undef DEF_FORMAT_ATTRIBUTE
+@@ -152,9 +161,24 @@
+ 
+ /* Functions from ISO/IEC 9899:1990.  */
+ #define DEF_C89_ATTR(NAME, ATTRS) DEF_FN_ATTR_IDENT (NAME, ATTRS, flag_hosted)
++DEF_C89_ATTR (printf, ATTR_FORMAT_PRINTF_1_2)
++DEF_C89_ATTR (fprintf, ATTR_FORMAT_PRINTF_2_3)
++DEF_C89_ATTR (sprintf, ATTR_FORMAT_PRINTF_2_3)
++DEF_C89_ATTR (scanf, ATTR_FORMAT_SCANF_1_2)
+ DEF_C89_ATTR (fscanf, ATTR_FORMAT_SCANF_2_3)
++DEF_C89_ATTR (sscanf, ATTR_FORMAT_SCANF_2_3)
++DEF_C89_ATTR (vprintf, ATTR_FORMAT_PRINTF_1_0)
+ DEF_C89_ATTR (vfprintf, ATTR_FORMAT_PRINTF_2_0)
++DEF_C89_ATTR (vsprintf, ATTR_FORMAT_PRINTF_2_0)
+ DEF_C89_ATTR (strftime, ATTR_FORMAT_STRFTIME_3_0)
++/* (TIGCC 20040219) */
++DEF_C89_ATTR (vcbprintf, ATTR_FORMAT_PRINTF_3_0)
++DEF_C89_ATTR (cbprintf, ATTR_FORMAT_PRINTF_3_4)
++DEF_C89_ATTR (vcbscanf, ATTR_FORMAT_SCANF_4_0)
++DEF_C89_ATTR (cbscanf, ATTR_FORMAT_SCANF_4_5)
++DEF_C89_ATTR (vscanf, ATTR_FORMAT_SCANF_1_0)
++DEF_C89_ATTR (vfscanf, ATTR_FORMAT_SCANF_2_0)
++DEF_C89_ATTR (vsscanf, ATTR_FORMAT_SCANF_2_0)
+ #undef DEF_C89_ATTR
+ 
+ /* ISO C99 adds the snprintf and vscanf family functions.  */
+@@ -162,7 +186,13 @@
+   DEF_FN_ATTR_IDENT (NAME, ATTRS,					    \
+ 	       (flag_hosted						    \
+ 		&& (flag_isoc99 || flag_noniso_default_format_attributes)))
++DEF_C99_ATTR (snprintf, ATTR_FORMAT_PRINTF_3_4)
++DEF_C99_ATTR (vsnprintf, ATTR_FORMAT_PRINTF_3_0)
++#if 0 /* (TIGCC 20040219) Moved these to C89, as we always define them. */
++DEF_C99_ATTR (vscanf, ATTR_FORMAT_SCANF_1_0)
+ DEF_C99_ATTR (vfscanf, ATTR_FORMAT_SCANF_2_0)
++DEF_C99_ATTR (vsscanf, ATTR_FORMAT_SCANF_2_0)
++#endif
+ #undef DEF_C99_ATTR
+ 
+ /* Functions not in any version of ISO C.  */
+diff -Naur gcc-3.3.3.orig/gcc/builtins.c gcc-3.3.3.tigcc8/gcc/builtins.c
+--- gcc-3.3.3.orig/gcc/builtins.c	Sun Jan 11 19:13:02 2004
++++ gcc-3.3.3.tigcc8/gcc/builtins.c	Thu Feb 19 21:20:00 2004
+@@ -143,13 +143,17 @@
+ static rtx expand_builtin_alloca	PARAMS ((tree, rtx));
+ static rtx expand_builtin_ffs		PARAMS ((tree, rtx, rtx));
+ static rtx expand_builtin_frame_address	PARAMS ((tree));
++#if 0
+ static rtx expand_builtin_fputs		PARAMS ((tree, int, int));
++#endif /* 0 */
+ static tree stabilize_va_list		PARAMS ((tree, int));
+ static rtx expand_builtin_expect	PARAMS ((tree, rtx));
+ static tree fold_builtin_constant_p	PARAMS ((tree));
+ static tree fold_builtin_classify_type	PARAMS ((tree));
++#if 0
+ static tree fold_builtin_inf		PARAMS ((tree, int));
+ static tree fold_builtin_nan		PARAMS ((tree, tree, int));
++#endif /* 0 */
+ static tree build_function_call_expr	PARAMS ((tree, tree));
+ static int validate_arglist		PARAMS ((tree, ...));
+ 
+@@ -915,7 +919,13 @@
+ 	size += GET_MODE_SIZE (Pmode);
+ 
+       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+-	if (FUNCTION_ARG_REGNO_P (regno))
++	if (0 /*FUNCTION_ARG_REGNO_P (regno)*/)
++	/* (TIGCC) Do NOT use register passing for __builtin_apply since:
++	           1. It doesn't work: ALL registers are POSSIBLE registers for
++	                               function parameters, so this code uses up all
++	                               registers.
++	           2. It significantly increases code size.
++	           3. The default calling convention is stkparm anyway. */
+ 	  {
+ 	    /* Search for the proper mode for copying this register's
+ 	       value.  I'm not sure this is right, but it works so far.  */
+@@ -3517,6 +3527,7 @@
+ /* If the string passed to fputs is a constant and is one character
+    long, we attempt to transform this call into __builtin_fputc().  */
+ 
++#if 0
+ static rtx
+ expand_builtin_fputs (arglist, ignore, unlocked)
+      tree arglist;
+@@ -3596,6 +3607,7 @@
+ 		      (ignore ? const0_rtx : NULL_RTX),
+ 		      VOIDmode, EXPAND_NORMAL);
+ }
++#endif /* 0 */
+ 
+ /* Expand a call to __builtin_expect.  We return our argument and emit a
+    NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
+@@ -3828,6 +3840,7 @@
+       case BUILT_IN_STRCSPN:
+       case BUILT_IN_STRCMP:
+       case BUILT_IN_FFS:
++#if 0
+       case BUILT_IN_PUTCHAR:
+       case BUILT_IN_PUTS:
+       case BUILT_IN_PRINTF:
+@@ -3840,6 +3853,7 @@
+       case BUILT_IN_FPUTC_UNLOCKED:
+       case BUILT_IN_FPUTS_UNLOCKED:
+       case BUILT_IN_FWRITE_UNLOCKED:
++#endif /* 0 */
+ 	return expand_call (exp, target, ignore);
+ 
+       default:
+@@ -4115,6 +4129,7 @@
+       expand_builtin_trap ();
+       return const0_rtx;
+ 
++#if 0
+     case BUILT_IN_FPUTS:
+       target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0);
+       if (target)
+@@ -4125,6 +4140,7 @@
+       if (target)
+ 	return target;
+       break;
++#endif /* 0 */
+ 
+       /* Various hooks for the DWARF 2 __throw routine.  */
+     case BUILT_IN_UNWIND_INIT:
+@@ -4230,6 +4246,7 @@
+   return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
+ }
+ 
++#if 0
+ /* Fold a call to __builtin_inf or __builtin_huge_val.  */
+ 
+ static tree
+@@ -4267,6 +4284,7 @@
+ 
+   return build_real (type, real);
+ }
++#endif /* 0 */
+ 
+ /* Used by constant folding to eliminate some builtin calls early.  EXP is
+    the CALL_EXPR of a call to a builtin function.  */
+@@ -4304,6 +4322,7 @@
+ 	}
+       break;
+ 
++#if 0
+     case BUILT_IN_INF:
+     case BUILT_IN_INFF:
+     case BUILT_IN_INFL:
+@@ -4323,6 +4342,7 @@
+     case BUILT_IN_NANSF:
+     case BUILT_IN_NANSL:
+       return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false);
++#endif /* 0 */
+ 
+     default:
+       break;
+diff -Naur gcc-3.3.3.orig/gcc/builtins.def gcc-3.3.3.tigcc8/gcc/builtins.def
+--- gcc-3.3.3.orig/gcc/builtins.def	Mon May  5 18:59:18 2003
++++ gcc-3.3.3.tigcc8/gcc/builtins.def	Thu Feb 19 21:20:00 2004
+@@ -525,6 +525,7 @@
+ 		BT_FN_VOID_CONST_PTR_VAR,
+ 		ATTR_NULL)
+ 
++#if 0
+ /* stdio.h builtins (without FILE *).  */
+ 
+ DEF_FRONT_END_LIB_BUILTIN(BUILT_IN_PRINTF,
+@@ -639,6 +640,7 @@
+ 			      "__builtin_fprintf_unlocked",
+ 			      BT_FN_INT_PTR_CONST_STRING_VAR,
+ 			      ATTR_FORMAT_PRINTF_2_3)
++#endif
+ 
+   /* ISO C99 floating point unordered comparisons.  */
+ DEF_GCC_BUILTIN(BUILT_IN_ISGREATER, 
+diff -Naur gcc-3.3.3.orig/gcc/c-common.c gcc-3.3.3.tigcc8/gcc/c-common.c
+--- gcc-3.3.3.orig/gcc/c-common.c	Sun Jun  8 00:13:24 2003
++++ gcc-3.3.3.tigcc8/gcc/c-common.c	Thu Feb 19 21:20:00 2004
+@@ -784,9 +784,11 @@
+                                                int));
+ static void builtin_define_with_int_value PARAMS ((const char *,
+ 						   HOST_WIDE_INT));
++#if 0
+ static void builtin_define_with_hex_fp_value PARAMS ((const char *, tree,
+ 						      int, const char *,
+ 						      const char *));
++#endif /* 0 */
+ static void builtin_define_type_max PARAMS ((const char *, tree, int));
+ static void builtin_define_type_precision PARAMS ((const char *, tree));
+ static void builtin_define_float_constants PARAMS ((const char *,
+@@ -1319,12 +1321,16 @@
+   return value;
+ }
+ 
++#if 0
+ static int is_valid_printf_arglist PARAMS ((tree));
++#endif /* 0 */
+ static rtx c_expand_builtin PARAMS ((tree, rtx, enum machine_mode, enum expand_modifier));
++#if 0
+ static rtx c_expand_builtin_printf PARAMS ((tree, rtx, enum machine_mode,
+ 					    enum expand_modifier, int, int));
+ static rtx c_expand_builtin_fprintf PARAMS ((tree, rtx, enum machine_mode,
+ 					     enum expand_modifier, int, int));
++#endif
+ 
+ /* Print a warning if a constant expression had overflow in folding.
+    Invoke this function on every expression that the language
+@@ -4427,6 +4433,7 @@
+ 
+   switch (fcode)
+     {
++#if 0
+     case BUILT_IN_PRINTF:
+       target = c_expand_builtin_printf (arglist, target, tmode,
+ 					modifier, ignore, /*unlocked=*/ 0);
+@@ -4454,6 +4461,7 @@
+       if (target)
+ 	return target;
+       break;
++#endif /* 0 */
+ 
+     default:			/* just do library call, if unknown builtin */
+       error ("built-in function `%s' not currently supported",
+@@ -4465,6 +4473,7 @@
+   return expand_call (exp, target, ignore);
+ }
+ 
++#if 0
+ /* Check an arglist to *printf for problems.  The arglist should start
+    at the format specifier, with the remaining arguments immediately
+    following it.  */
+@@ -4686,6 +4695,7 @@
+ 		      (ignore ? const0_rtx : target),
+ 		      tmode, modifier);
+ }
++#endif /* 0 */
+ 
+ 
+ /* Given a boolean expression ARG, return a tree representing an increment
+@@ -4744,6 +4754,7 @@
+      const char *fp_suffix;
+      tree type;
+ {
++#if 0 /* (TIGCC) Do nothing. We have our own float.h! */
+   /* Used to convert radix-based values to base 10 values in several cases.
+ 
+      In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at
+@@ -4899,6 +4910,7 @@
+       sprintf (buf, "0.0%s", fp_suffix);
+       builtin_define_with_value (name, buf, 0);
+     }
++#endif /* 0 */
+ }
+ 
+ /* Hook that registers front end and target-specific built-ins.  */
+@@ -5099,6 +5111,7 @@
+   cpp_define (parse_in, buf);
+ }
+ 
++#if 0
+ /* Pass an object-like macro a hexadecimal floating-point value.  */
+ static void
+ builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
+@@ -5127,6 +5140,7 @@
+   sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
+   cpp_define (parse_in, buf);
+ }
++#endif /* 0 */
+ 
+ /* Define MAX for TYPE based on the precision of the type.  IS_LONG is
+    1 for type "long" and 2 for "long long".  We have to handle
+diff -Naur gcc-3.3.3.orig/gcc/c-decl.c gcc-3.3.3.tigcc8/gcc/c-decl.c
+--- gcc-3.3.3.orig/gcc/c-decl.c	Sat Sep  6 16:44:14 2003
++++ gcc-3.3.3.tigcc8/gcc/c-decl.c	Thu Feb 19 21:20:00 2004
+@@ -3225,8 +3225,10 @@
+    record the given order of parms in `parm_order'.  */
+ 
+ void
+-push_parm_decl (parm)
+-     tree parm;
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++push_parm_decl (parm, asmspec)
++     tree parm, asmspec;
++/* end-TIGCC-local (regparms) */
+ {
+   tree decl;
+   int old_immediate_size_expand = immediate_size_expand;
+@@ -3248,6 +3250,78 @@
+     }
+ #endif
+ 
++  /* begin-TIGCC-local (regparms): explicit register specification for parameters */
++  if (asmspec)
++#ifdef EXPLICIT_REGPARM
++    {
++      const char *regname=TREE_STRING_POINTER(asmspec);
++      int regnum;
++      if ((regnum=decode_reg_name(regname))>=0)
++	{
++	  tree type=TREE_TYPE(decl);
++	  if (HARD_REGNO_MODE_OK(regnum, TYPE_MODE(type)))
++	    {
++	      tree t, attrs;
++/*	      push_obstacks_nochange();
++	      end_temporary_allocation(); */
++	      /* Build tree for __attribute__ ((asm(regnum))). */
++#if 0
++	      /* This doesn't work well because of a bug in
++		 attribute_list_contained(), which passes list of arguments to
++		 simple_cst_equal() instead of passing every argument
++		 separately. */
++	      attrs=tree_cons(get_identifier("asm"), tree_cons(NULL_TREE,
++		    build_int_2_wide(regnum, 0), NULL_TREE), NULL_TREE);
++#else
++	      attrs=tree_cons(get_identifier("asm"),
++			      build_int_2_wide(regnum, 0), NULL_TREE);
++#endif
++#if 0
++	      /* build_type_attribute_variant() would seem to be more
++		 appropriate here. However, that function does not support
++		 attributes for parameters properly. It modifies
++		 TYPE_MAIN_VARIANT of a new type. As a result, comptypes()
++		 thinks that types of parameters in prototype and definition
++		 are different and issues error messages. See also comment
++		 below. */
++	      type=build_type_attribute_variant(type, attrs);
++#else
++	      /* First check whether such a type already exists - if yes, use
++		 that one. This is very important, since otherwise
++		 common_type() would think that it sees two different
++		 types and would try to merge them - this could result in
++		 warning messages. */
++	      for (t=TYPE_MAIN_VARIANT(type); t; t=TYPE_NEXT_VARIANT(t))
++		if (comptypes(t, type)==1
++		    && attribute_list_equal(TYPE_ATTRIBUTES(t), attrs))
++		      break;
++	      if (t)
++		type=t;
++	      else
++		{
++		  /* Create a new variant, with differing attributes.
++		     (Hack! Type with differing attributes should no longer be
++		     a variant of its main type. See comment above for
++		     explanation why this was necessary). */
++		  type=build_type_copy(type);
++		  TYPE_ATTRIBUTES(type)=attrs;
++		}
++#endif
++	      TREE_TYPE(decl)=type;
++/*	      pop_obstacks(); */
++	    }
++	  else
++	    error_with_decl(decl,
++		"register number for `%s' isn't suitable for the data type");
++	}
++      else
++	error("invalid register name `%s'", regname);
++    }
++#else /* !EXPLICIT_REGPARM */
++    error("explicit register specification for parameters is not supported for this target");
++#endif
++  /* end-TIGCC-local (regparms) */
++
+   decl = pushdecl (decl);
+ 
+   immediate_size_expand = old_immediate_size_expand;
+@@ -3279,6 +3353,21 @@
+      tree type;
+      tree init;
+ {
++  /* (TIGCC) If -fglobal-compound-literals (on by default) is given, for
++     constant constructors, the compound literal is just the constructor itself.
++     For variable constructors, we use the new code, since they have to be
++     created on the stack anyway, and since the new code allows taking their
++     address.  */
++if (flag_global_compound_literals && TREE_CONSTANT (init)) {
++  if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
++    {
++      int failure = complete_array_type (type, init, 1);
++      if (failure)
++	abort ();
++    }
++
++  return init;
++} else {
+   /* We do not use start_decl here because we have a type, not a declarator;
+      and do not use finish_decl because the decl should be stored inside
+      the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT.  */
+@@ -3329,6 +3418,7 @@
+     }
+ 
+   return complit;
++}
+ }
+ 
+ /* Make TYPE a complete type based on INITIAL_VALUE.
+diff -Naur gcc-3.3.3.orig/gcc/c-format.c gcc-3.3.3.tigcc8/gcc/c-format.c
+--- gcc-3.3.3.orig/gcc/c-format.c	Sun Dec  1 17:51:44 2002
++++ gcc-3.3.3.tigcc8/gcc/c-format.c	Wed Jul 28 00:18:00 2004
+@@ -559,30 +559,22 @@
+ } format_wanted_type;
+ 
+ 
++/* (TIGCC 20040219) AMS doesn't support any C99 or extended modifiers.
++    -- Kevin Kofler */
+ static const format_length_info printf_length_specs[] =
+ {
+-  { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
+-  { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
+-  { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
+-  { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
+-  { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
+-  { "Z", FMT_LEN_z, STD_EXT, NULL, 0, 0 },
+-  { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
+-  { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 },
++  { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
++  { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
+   { NULL, 0, 0, NULL, 0, 0 }
+ };
+ 
+ 
+-/* This differs from printf_length_specs only in that "Z" is not accepted.  */
++/* (TIGCC 20040219) My *scanf doesn't support any C99 or extended modifiers.
++    -- Kevin Kofler */
+ static const format_length_info scanf_length_specs[] =
+ {
+-  { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
+-  { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
+-  { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
+-  { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
+-  { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
+-  { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
+-  { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 },
++  { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
++  { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
+   { NULL, 0, 0, NULL, 0, 0 }
+ };
+ 
+@@ -596,6 +588,9 @@
+   { NULL, 0, 0, NULL, 0, 0 }
+ };
+ 
++/* (TIGCC 20040219) AMS doesn't support any of the GNU extended modifiers.
++                    However, it supports some of its own.
++    -- Kevin Kofler */
+ static const format_flag_spec printf_flag_specs[] =
+ {
+   { ' ',  0, 0, N_("` ' flag"),        N_("the ` ' printf flag"),              STD_C89 },
+@@ -603,8 +598,9 @@
+   { '#',  0, 0, N_("`#' flag"),        N_("the `#' printf flag"),              STD_C89 },
+   { '0',  0, 0, N_("`0' flag"),        N_("the `0' printf flag"),              STD_C89 },
+   { '-',  0, 0, N_("`-' flag"),        N_("the `-' printf flag"),              STD_C89 },
+-  { '\'', 0, 0, N_("`'' flag"),        N_("the `'' printf flag"),              STD_EXT },
+-  { 'I',  0, 0, N_("`I' flag"),        N_("the `I' printf flag"),              STD_EXT },
++  { 'z',  0, 0, N_("`z' flag"),        N_("the `z' printf flag"),              STD_EXT },
++  { '^',  0, 0, N_("`^' flag"),        N_("the `^' printf flag"),              STD_EXT },
++  { '|',  0, 0, N_("`|' flag"),        N_("the `|' printf flag"),              STD_EXT },
+   { 'w',  0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
+   { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
+   { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
+@@ -621,14 +617,13 @@
+ };
+ 
+ 
++/* (TIGCC 20040219) My *scanf doesn't support any extended modifiers.
++    -- Kevin Kofler */
+ static const format_flag_spec scanf_flag_specs[] =
+ {
+   { '*',  0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
+-  { 'a',  0, 0, N_("`a' flag"),               N_("the `a' scanf flag"),                       STD_EXT },
+   { 'w',  0, 0, N_("field width"),            N_("field width in scanf format"),              STD_C89 },
+   { 'L',  0, 0, N_("length modifier"),        N_("length modifier in scanf format"),          STD_C89 },
+-  { '\'', 0, 0, N_("`'' flag"),               N_("the `'' scanf flag"),                       STD_EXT },
+-  { 'I',  0, 0, N_("`I' flag"),               N_("the `I' scanf flag"),                       STD_EXT },
+   { 0, 0, 0, NULL, NULL, 0 }
+ };
+ 
+@@ -742,46 +737,37 @@
+ #define T_UIM   &uintmax_type_node
+ #define T99_UIM	{ STD_C99, "uintmax_t", T_UIM }
+ 
++/* (TIGCC 20040219) AMS doesn't support any of the C99 or GNU extended
++                    modifiers. However, it supports some of its own.
++    -- Kevin Kofler */
+ static const format_char_info print_char_table[] =
+ {
+   /* C89 conversion specifiers.  */
+-  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "-wp0 +'I", "i"  },
+-  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0#",    "i"  },
+-  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0'I",   "i"  },
+-  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'", ""   },
+-  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  ""   },
+-  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       ""   },
+-  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "cR" },
+-  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       "c"  },
+-  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",         "W"  },
+-  /* C99 conversion specifiers.  */
+-  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'", ""   },
+-  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  ""   },
+-  /* X/Open conversion specifiers.  */
+-  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       ""   },
+-  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "R"  },
+-  /* GNU conversion specifiers.  */
+-  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      ""   },
++  { "di",  0, STD_C89, { T89_S,   BADLEN,  T89_S,   T89_L,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +|z",  "i"  },
++  { "xX", 0, STD_C89, { T89_US,  BADLEN,  T89_US,  T89_UL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0#|z",     "i"  },
++  { "u",   0, STD_C89, { T89_US,  BADLEN,  T89_US,  T89_UL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0|z",    "i"  },
++  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z", ""   },
++  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z",  ""   },
++  { "rR",  0, STD_EXT, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z",  ""   },
++  { "yY",  0, STD_EXT, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#^|z",  ""   },
++  { "c",   0, STD_C89, { T89_S,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w|z",        ""   },
++  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp|z",       "cR" },
++  { "p",   1, STD_C89, { BADLEN,  BADLEN,  BADLEN,  T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w|z",        "c"  },
+   { NULL,  0, 0, NOLENGTHS, NULL, NULL }
+ };
+ 
++/* (TIGCC 20040219) My *scanf doesn't support any extended modifiers. -- Kevin Kofler */
+ static const format_char_info scan_char_table[] =
+ {
+   /* C89 conversion specifiers.  */
+-  { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "*w'I", "W"   },
+-  { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w'I", "W"   },
++  { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "*w", "W"   },
++  { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w", "W"   },
+   { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w",   "W"   },
+-  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w'",  "W"   },
++  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w",  "W"   },
+   { "c",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "cW"  },
+   { "s",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "cW"  },
+   { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "cW[" },
+   { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "W"   },
+-  { "n",     1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",     "W"   },
+-  /* C99 conversion specifiers.  */
+-  { "FaA",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w'",  "W"   },
+-  /* X/Open conversion specifiers.  */
+-  { "C",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "W"   },
+-  { "S",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "W"   },
+   { NULL, 0, 0, NOLENGTHS, NULL, NULL }
+ };
+ 
+@@ -820,15 +806,16 @@
+ 
+ 
+ /* This must be in the same order as enum format_type.  */
++/* (TIGCC 20040219) Changed the flag chars. See the *f_flag_specs comments. */
+ static const format_kind_info format_types[] =
+ {
+-  { "printf",   printf_length_specs,  print_char_table, " +#0-'I", NULL, 
++  { "printf",   printf_length_specs,  print_char_table, " +#0-z^|", NULL, 
+     printf_flag_specs, printf_flag_pairs,
+     FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
+     'w', 0, 'p', 0, 'L',
+     &integer_type_node, &integer_type_node
+   },
+-  { "scanf",    scanf_length_specs,   scan_char_table,  "*'I", NULL, 
++  { "scanf",    scanf_length_specs,   scan_char_table,  "*", NULL, 
+     scanf_flag_specs, scanf_flag_pairs,
+     FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
+     'w', 0, 0, '*', 'L',
+@@ -2275,6 +2262,17 @@
+ 			  || cur_type == signed_char_type_node
+ 			  || cur_type == unsigned_char_type_node);
+ 
++      /* (TIGCC) Account for *printf and *scanf not actually supporting -mlong.  */
++      if (!TARGET_SHORT) {
++        if (cur_type == short_integer_type_node
++            || cur_type == integer_type_node)
++          orig_cur_type = cur_type = long_integer_type_node;
++
++        if (cur_type == short_unsigned_type_node
++            || cur_type == unsigned_type_node)
++          orig_cur_type = cur_type = long_unsigned_type_node;
++      }
++
+       /* Check the type of the "real" argument, if there's a type we want.  */
+       if (wanted_type == cur_type)
+ 	continue;
+@@ -2289,12 +2287,18 @@
+ 	 -pedantic.  With -pedantic, warn if the type is a pointer
+ 	 target and not a character type, and for character types at
+ 	 a second level of indirection.  */
+-      if (TREE_CODE (wanted_type) == INTEGER_TYPE
++      /* TIGCC Patch: Don't warn about differences in floating point
++         format; they're all the same.
++         (TIGCC 20040728) But do warn if someone passes an integer where a float
++                          is expected! -- Kevin Kofler  */
++      if ((TREE_CODE (wanted_type) == REAL_TYPE
++           && TREE_CODE (cur_type) == REAL_TYPE)
++	  || (TREE_CODE (wanted_type) == INTEGER_TYPE
+ 	  && TREE_CODE (cur_type) == INTEGER_TYPE
+ 	  && (! pedantic || i == 0 || (i == 1 && char_type_flag))
+ 	  && (TREE_UNSIGNED (wanted_type)
+ 	      ? wanted_type == c_common_unsigned_type (cur_type)
+-	      : wanted_type == c_common_signed_type (cur_type)))
++	      : wanted_type == c_common_signed_type (cur_type))))
+ 	continue;
+       /* Likewise, "signed char", "unsigned char" and "char" are
+ 	 equivalent but the above test won't consider them equivalent.  */
+diff -Naur gcc-3.3.3.orig/gcc/c-lex.c gcc-3.3.3.tigcc8/gcc/c-lex.c
+--- gcc-3.3.3.orig/gcc/c-lex.c	Sun Sep 14 15:26:34 2003
++++ gcc-3.3.3.tigcc8/gcc/c-lex.c	Thu Feb 19 21:20:00 2004
+@@ -929,8 +929,7 @@
+   memcpy (copy, token->val.str.text, copylen);
+   copy[copylen] = '\0';
+ 
+-  real_from_string (&real, copy);
+-  real_convert (&real, TYPE_MODE (type), &real);
++  real = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ 
+   /* A diagnostic is required for "soft" overflow by some ISO C
+      testsuites.  This is not pedwarn, because some people don't want
+diff -Naur gcc-3.3.3.orig/gcc/c-opts.c gcc-3.3.3.tigcc8/gcc/c-opts.c
+--- gcc-3.3.3.orig/gcc/c-opts.c	Thu Jun 12 13:58:30 2003
++++ gcc-3.3.3.tigcc8/gcc/c-opts.c	Thu Feb 19 21:20:00 2004
+@@ -193,6 +193,7 @@
+   OPT("fall-virtual",		CL_CXX,   OPT_fall_virtual)		     \
+   OPT("falt-external-templates",CL_CXX,   OPT_falt_external_templates)	     \
+   OPT("fasm",			CL_ALL,   OPT_fasm)			     \
++  OPT("fauto-octals",	CL_ALL,   OPT_fauto_octals)	     \
+   OPT("fbuiltin",		CL_ALL,   OPT_fbuiltin)			     \
+   OPT("fbuiltin-",		CL_ALL | CL_JOINED, OPT_fbuiltin_)	     \
+   OPT("fcheck-new",		CL_CXX,   OPT_fcheck_new)		     \
+@@ -1339,6 +1340,10 @@
+ 
+     case OPT_v:
+       cpp_opts->verbose = 1;
++      break;
++
++    case OPT_fauto_octals:
++      cpp_opts->no_auto_octals = !on;
+       break;
+     }
+ 
+diff -Naur gcc-3.3.3.orig/gcc/c-parse.in gcc-3.3.3.tigcc8/gcc/c-parse.in
+--- gcc-3.3.3.orig/gcc/c-parse.in	Tue Jan 28 01:54:02 2003
++++ gcc-3.3.3.tigcc8/gcc/c-parse.in	Thu Feb 19 21:20:02 2004
+@@ -29,7 +29,7 @@
+    written by AT&T, but I have never seen it.  */
+ 
+ ifc
+-%expect 10 /* shift/reduce conflicts, and no reduce/reduce conflicts.  */
++%expect 11 /* shift/reduce conflicts, and no reduce/reduce conflicts.  */
+ end ifc
+ 
+ %{
+@@ -225,7 +225,7 @@
+ %type <ttype> enumlist enumerator
+ %type <ttype> struct_head union_head enum_head
+ %type <ttype> typename absdcl absdcl1 absdcl1_ea absdcl1_noea
+-%type <ttype> direct_absdcl1 absdcl_maybe_attribute
++%type <ttype> direct_absdcl1 /*(TIGCC)*/ absdcl_maybeasm_maybe_attribute
+ %type <ttype> xexpr parms parm firstparm identifiers
+ 
+ %type <ttype> parmlist parmlist_1 parmlist_2
+@@ -1943,20 +1943,22 @@
+ 	| absdcl1
+ 	;
+ 
+-absdcl_maybe_attribute:   /* absdcl maybe_attribute, but not just attributes */
+-	/* empty */
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++absdcl_maybeasm_maybe_attribute:   /* absdcl maybeasm maybe_attribute, but not just attributes */
++	maybeasm
++		{ $$ = build_tree_list (build_tree_list (build_tree_list (current_declspecs,
+ 							 NULL_TREE),
+-					all_prefix_attributes); }
+-	| absdcl1
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++					all_prefix_attributes), $1); }
++	| absdcl1 maybeasm
++		{ $$ = build_tree_list (build_tree_list (build_tree_list (current_declspecs,
+ 							 $1),
+-					all_prefix_attributes); }
+-	| absdcl1_noea attributes
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++					all_prefix_attributes), $2); }
++	| absdcl1_noea maybeasm attributes
++		{ $$ = build_tree_list (build_tree_list (build_tree_list (current_declspecs,
+ 							 $1),
+-					chainon ($2, all_prefix_attributes)); }
++					chainon ($3, all_prefix_attributes)), $2); }
+ 	;
++ /* end-TIGCC-local (regparms) */
+ 
+ absdcl1:  /* a nonempty absolute declarator */
+ 	  absdcl1_ea
+@@ -2552,34 +2554,38 @@
+ 
+ parms:
+ 	firstparm
+-		{ push_parm_decl ($1); }
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++		{ push_parm_decl (TREE_PURPOSE($1), TREE_VALUE($1)); }
+ 	| parms ',' parm
+-		{ push_parm_decl ($3); }
++		{ push_parm_decl (TREE_PURPOSE($3), TREE_VALUE($3)); }
+ 	;
+ 
+ /* A single parameter declaration or parameter type name,
+    as found in a parmlist.  */
+ parm:
+-	  declspecs_ts setspecs parm_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	  declspecs_ts setspecs parm_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $3),
+-					chainon ($4, all_prefix_attributes));
++					chainon ($5, all_prefix_attributes)), $4);
+ 		  POP_DECLSPEC_STACK; }
+-	| declspecs_ts setspecs notype_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	| declspecs_ts setspecs notype_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $3),
+-					chainon ($4, all_prefix_attributes));
++					chainon ($5, all_prefix_attributes)), $4);
+ 		  POP_DECLSPEC_STACK; }
+-	| declspecs_ts setspecs absdcl_maybe_attribute
++	| declspecs_ts setspecs absdcl_maybeasm_maybe_attribute
+ 		{ $$ = $3;
+ 		  POP_DECLSPEC_STACK; }
+-	| declspecs_nots setspecs notype_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	| declspecs_nots setspecs notype_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $3),
+-					chainon ($4, all_prefix_attributes));
++					chainon ($5, all_prefix_attributes)), $4);
+ 		  POP_DECLSPEC_STACK; }
+ 
+-	| declspecs_nots setspecs absdcl_maybe_attribute
++	| declspecs_nots setspecs absdcl_maybeasm_maybe_attribute
+ 		{ $$ = $3;
+ 		  POP_DECLSPEC_STACK; }
+ 	;
+@@ -2587,29 +2593,33 @@
+ /* The first parm, which must suck attributes from off the top of the parser
+    stack.  */
+ firstparm:
+-	  declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	  declspecs_ts_nosa setspecs_fp parm_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $3),
+-					chainon ($4, all_prefix_attributes));
++					chainon ($5, all_prefix_attributes)), $4);
+ 		  POP_DECLSPEC_STACK; }
+-	| declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	| declspecs_ts_nosa setspecs_fp notype_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $3),
+-					chainon ($4, all_prefix_attributes));
++					chainon ($5, all_prefix_attributes)), $4);
+ 		  POP_DECLSPEC_STACK; }
+-	| declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute
++	| declspecs_ts_nosa setspecs_fp absdcl_maybeasm_maybe_attribute
+ 		{ $$ = $3;
+ 		  POP_DECLSPEC_STACK; }
+-	| declspecs_nots_nosa setspecs_fp notype_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	| declspecs_nots_nosa setspecs_fp notype_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $3),
+-					chainon ($4, all_prefix_attributes));
++					chainon ($5, all_prefix_attributes)), $4);
+ 		  POP_DECLSPEC_STACK; }
+ 
+-	| declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute
++	| declspecs_nots_nosa setspecs_fp absdcl_maybeasm_maybe_attribute
+ 		{ $$ = $3;
+ 		  POP_DECLSPEC_STACK; }
+ 	;
++/* end-TIGCC-local (regparms) */
+ 
+ setspecs_fp:
+ 	  setspecs
+@@ -3084,26 +3094,30 @@
+ 
+ myparms:
+ 	myparm
+-		{ push_parm_decl ($1); }
+-	| myparms ',' myparm
+-		{ push_parm_decl ($3); }
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++		{ push_parm_decl (TREE_PURPOSE($1), TREE_VALUE($1)); }
++  	| myparms ',' myparm
++		{ push_parm_decl (TREE_PURPOSE($3), TREE_VALUE($3)); }
+ 	;
+ 
+ /* A single parameter declaration or parameter type name,
+-   as found in a parmlist. DOES NOT ALLOW AN INITIALIZER OR ASMSPEC */
++   as found in a parmlist. DOES NOT ALLOW AN INITIALIZER */
+ 
+ myparm:
+-	  parm_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++	  parm_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $1),
+-					chainon ($2, all_prefix_attributes)); }
+-	| notype_declarator maybe_attribute
+-		{ $$ = build_tree_list (build_tree_list (current_declspecs,
++					chainon ($3, all_prefix_attributes)), $2); }
++	| notype_declarator maybeasm maybe_attribute
++		{ $$ = build_tree_list (
++			 build_tree_list (build_tree_list (current_declspecs,
+ 							 $1),
+-					chainon ($2, all_prefix_attributes)); }
+-	| absdcl_maybe_attribute
++					chainon ($3, all_prefix_attributes)), $2); }
++	| absdcl_maybeasm_maybe_attribute
+ 		{ $$ = $1; }
+ 	;
++/* end-TIGCC-local (regparms) */
+ 
+ optparmlist:
+ 	  /* empty */
+diff -Naur gcc-3.3.3.orig/gcc/c-pretty-print.c gcc-3.3.3.tigcc8/gcc/c-pretty-print.c
+--- gcc-3.3.3.orig/gcc/c-pretty-print.c	Wed Oct 16 02:40:26 2002
++++ gcc-3.3.3.tigcc8/gcc/c-pretty-print.c	Thu Feb 19 21:20:02 2004
+@@ -469,9 +469,8 @@
+      c_pretty_printer ppi;
+      tree r;
+ {
+-  real_to_decimal (pp_buffer (ppi)->digit_buffer, &TREE_REAL_CST (r),
+-		   sizeof (pp_buffer (ppi)->digit_buffer), 0, 1);
+-  pp_identifier (ppi, pp_buffer(ppi)->digit_buffer);
++  REAL_VALUE_TO_STRING (TREE_REAL_CST (r), pp_buffer (ppi)->digit_buffer);
++  pp_identifier (ppi, pp_buffer (ppi)->digit_buffer);
+ }
+ 
+ 
+diff -Naur gcc-3.3.3.orig/gcc/c-tree.h gcc-3.3.3.tigcc8/gcc/c-tree.h
+--- gcc-3.3.3.orig/gcc/c-tree.h	Mon Sep 16 20:33:18 2002
++++ gcc-3.3.3.tigcc8/gcc/c-tree.h	Thu Feb 19 21:20:02 2004
+@@ -222,7 +222,9 @@
+ extern void c_pop_function_context              PARAMS ((struct function *));
+ extern void pop_label_level                     PARAMS ((void));
+ extern void push_label_level                    PARAMS ((void));
+-extern void push_parm_decl                      PARAMS ((tree));
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++extern void push_parm_decl                      PARAMS ((tree, tree));
++/* end-TIGCC-local (regparms) */
+ extern tree pushdecl_top_level                  PARAMS ((tree));
+ extern void pushtag                             PARAMS ((tree, tree));
+ extern tree set_array_declarator_type           PARAMS ((tree, tree, int));
+diff -Naur gcc-3.3.3.orig/gcc/c-typeck.c gcc-3.3.3.tigcc8/gcc/c-typeck.c
+--- gcc-3.3.3.orig/gcc/c-typeck.c	Tue Dec 23 06:23:32 2003
++++ gcc-3.3.3.tigcc8/gcc/c-typeck.c	Thu Feb 19 21:20:02 2004
+@@ -47,9 +47,6 @@
+    message within this initializer.  */
+ static int missing_braces_mentioned;
+ 
+-/* 1 if we explained undeclared var errors.  */
+-static int undeclared_variable_notice;
+-
+ static tree qualify_type		PARAMS ((tree, tree));
+ static int comp_target_types		PARAMS ((tree, tree, int));
+ static int function_types_compatible_p	PARAMS ((tree, tree));
+@@ -876,7 +873,10 @@
+ 	}
+ 
+       lvalue_array_p = !not_lvalue && lvalue_p (exp);
+-      if (!flag_isoc99 && !lvalue_array_p)
++
++      if (!flag_isoc99 && !lvalue_array_p
++          && !(flag_global_compound_literals
++               && (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) )
+ 	{
+ 	  /* Before C99, non-lvalue arrays do not decay to pointers.
+ 	     Normally, using such an array would be invalid; but it can
+@@ -1417,13 +1417,6 @@
+ 		{
+ 		  error ("`%s' undeclared (first use in this function)",
+ 			 IDENTIFIER_POINTER (id));
+-
+-		  if (! undeclared_variable_notice)
+-		    {
+-		      error ("(Each undeclared identifier is reported only once");
+-		      error ("for each function it appears in.)");
+-		      undeclared_variable_notice = 1;
+-		    }
+ 		}
+ 	      IDENTIFIER_GLOBAL_VALUE (id) = error_mark_node;
+ 	      IDENTIFIER_ERROR_LOCUS (id) = current_function_decl;
+@@ -3033,6 +3026,12 @@
+ 	}
+ #endif
+ 
++      /* (TIGCC) In global compound literal mode, allow the address of a
++	 constructor if all the elements are constant.  */
++      if (flag_global_compound_literals
++          && (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg)))
++	;
++
+       /* Anything not already handled and not a true memory reference
+ 	 or a non-lvalue array is an error.  */
+       else if (typecode != FUNCTION_TYPE && !flag
+@@ -4646,10 +4645,11 @@
+ {
+   char *ofwhat;
+ 
+-  error ("%s", _(msgid));
+   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+   if (*ofwhat)
+-    error ("(near initialization for `%s')", ofwhat);
++    error ("%s (near initialization for `%s')", _(msgid), ofwhat);
++  else
++    error ("%s", _(msgid));
+ }
+ 
+ /* Issue a pedantic warning for a bad initializer component.
+@@ -4662,10 +4662,11 @@
+ {
+   char *ofwhat;
+ 
+-  pedwarn ("%s", _(msgid));
+   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+   if (*ofwhat)
+-    pedwarn ("(near initialization for `%s')", ofwhat);
++    pedwarn ("%s (near initialization for `%s')", _(msgid), ofwhat);
++  else
++    pedwarn ("%s", _(msgid));
+ }
+ 
+ /* Issue a warning for a bad initializer component.
+@@ -4678,10 +4679,11 @@
+ {
+   char *ofwhat;
+ 
+-  warning ("%s", _(msgid));
+   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+   if (*ofwhat)
+-    warning ("(near initialization for `%s')", ofwhat);
++    warning ("%s (near initialization for `%s')", _(msgid), ofwhat);
++  else
++    warning ("%s", _(msgid));
+ }
+ 
+ /* Digest the parser output INIT as an initializer for type TYPE.
+diff -Naur gcc-3.3.3.orig/gcc/collect2.c gcc-3.3.3.tigcc8/gcc/collect2.c
+--- gcc-3.3.3.orig/gcc/collect2.c	Mon Dec  8 19:02:38 2003
++++ gcc-3.3.3.tigcc8/gcc/collect2.c	Thu Feb 19 21:20:02 2004
+@@ -161,6 +161,64 @@
+ #define SCAN_LIBRARIES
+ #endif
+ 
++/* Patch to allow collect2 to build on MinGW by Lev Serebryakov */
++#ifdef __MINGW32__
++/* We are being compiled with mingw32 as host, so we should prepare some
++   win32 replaces for pipe(), kill(getpid(),...) and vfork() + execv()
++*/
++#include <io.h>
++#include <fcntl.h>
++
++#define pipe(fildes) _pipe((fildes),1024*16,_O_BINARY)
++
++#define WIN32_LEAN_AND_MEAN
++#include <windows.h>
++
++int vfork_execv(char *cmdname, char **argv, int fdout);
++
++/* Helper function for vfork() + execv() replacement. */
++int vfork_execv(char *cmdname, char **argv, int fdout)
++{
++	STARTUPINFO SI;
++	PROCESS_INFORMATION PI;
++	char *params;
++	int plen = 0;
++	int i;
++	BOOL bRes;
++
++	/* Prepare one line with arguments */
++	for(i=0;argv[i];i++) plen += strlen(argv[i]) + 1;
++	plen++;
++	params = xmalloc(plen);
++	strcpy(params,argv[0]);
++	for(i=1;argv[i];i++)  strcat(strcat(params," "),argv[i]);
++
++	/* Prepare startup info -- for pipes redirection */
++	memset(&SI,0,sizeof(SI));
++	SI.cb = sizeof(SI);
++	SI.dwFlags = STARTF_USESTDHANDLES;
++	SI.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
++	SI.hStdOutput = (HANDLE)_get_osfhandle(fdout);
++	SI.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
++
++	/* Create new process in same console, with redirected (piped) stdout */
++	bRes = CreateProcess(cmdname,params,
++		NULL,NULL,	/* Security attributes */
++		FALSE,		/* Handle inheritance */
++		0,			/* Flags -- default, in this console, etc */
++		NULL,		/* Invironment */
++		NULL,		/* CWD */
++		&SI,		/* Startup info */
++		&PI);		/* Process info */
++	if(!bRes) return -1;
++	CloseHandle(PI.hProcess);
++	CloseHandle(PI.hThread);
++	return 0;
++}
++
++/* END-OF-WIN32-SECTION */
++#endif
++
+ #ifdef USE_COLLECT2
+ int do_collecting = 1;
+ #else
+@@ -444,7 +502,11 @@
+ #endif
+ 
+   signal (signo, SIG_DFL);
++#ifndef __MINGW32__
+   kill (getpid (), signo);
++#else
++  ExitProcess(signo);
++#endif
+ }
+ 
+ 
+@@ -2111,6 +2173,7 @@
+   fflush (stderr);
+ 
+   /* Spawn child nm on pipe */
++#ifndef __MINGW32__
+   pid = vfork ();
+   if (pid == -1)
+     fatal_perror (VFORK_STRING);
+@@ -2130,6 +2193,11 @@
+       execv (nm_file_name, real_nm_argv);
+       fatal_perror ("execv %s", nm_file_name);
+     }
++#else
++  if(vfork_execv(nm_file_name, real_nm_argv, pipe_fd[1])) {
++      fatal_perror ("vfork+execv %s", nm_file_name);
++  }
++#endif
+ 
+   /* Parent context from here on.  */
+   int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
+@@ -2552,6 +2620,7 @@
+   fflush (stderr);
+ 
+   /* Spawn child ldd on pipe */
++#ifndef __MINGW32__
+   pid = vfork ();
+   if (pid == -1)
+     fatal_perror (VFORK_STRING);
+@@ -2571,6 +2640,11 @@
+       execv (ldd_file_name, real_ldd_argv);
+       fatal_perror ("execv %s", ldd_file_name);
+     }
++#else
++  if(vfork_execv(ldd_file_name, real_ldd_argv, pipe_fd[1])) {
++      fatal_perror ("vfork+execv %s", nm_file_name);
++  }
++#endif
+ 
+   /* Parent context from here on.  */
+   int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
+diff -Naur gcc-3.3.3.orig/gcc/combine.c gcc-3.3.3.tigcc8/gcc/combine.c
+--- gcc-3.3.3.orig/gcc/combine.c	Fri Jan 23 20:42:48 2004
++++ gcc-3.3.3.tigcc8/gcc/combine.c	Thu Feb 19 21:20:02 2004
+@@ -1477,10 +1477,19 @@
+   if (! INSN_P (insn))
+     return 1;
+ 
+-  /* Never combine loads and stores involving hard regs.  The register
+-     allocator can usually handle such reg-reg moves by tying.  If we allow
+-     the combiner to make substitutions of hard regs, we risk aborting in
+-     reload on machines that have SMALL_REGISTER_CLASSES.
++/* (TIGCC 20040219) Backport from mainline:
++2003-04-16  J"orn Rennecke <joern.rennecke@superh.com>
++
++	Re-apply this patch:
++
++	2002-05-16  Dale Johannesen  <dalej@apple.com>
++	  * combine.c (cant_combine_insn_p):  Reenable combinations
++	  involving hard regs unless CLASS_LIKELY_SPILLED_P.
++-- Kevin Kofler */
++  /* Never combine loads and stores involving hard regs that are likely
++     to be spilled.  The register allocator can usually handle such
++     reg-reg moves by tying.  If we allow the combiner to make
++     substitutions of likely-spilled regs, we may abort in reload.
+      As an exception, we allow combinations involving fixed regs; these are
+      not available to the register allocator so there's no risk involved.  */
+ 
+@@ -1495,9 +1504,11 @@
+     dest = SUBREG_REG (dest);
+   if (REG_P (src) && REG_P (dest)
+       && ((REGNO (src) < FIRST_PSEUDO_REGISTER
+-	   && ! fixed_regs[REGNO (src)])
++         && ! fixed_regs[REGNO (src)]
++         && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
+ 	  || (REGNO (dest) < FIRST_PSEUDO_REGISTER
+-	      && ! fixed_regs[REGNO (dest)])))
++            && ! fixed_regs[REGNO (dest)]
++            && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
+     return 1;
+ 
+   return 0;
+diff -Naur gcc-3.3.3.orig/gcc/config/dbxcoff.h gcc-3.3.3.tigcc8/gcc/config/dbxcoff.h
+--- gcc-3.3.3.orig/gcc/config/dbxcoff.h	Sun Sep 29 15:16:44 2002
++++ gcc-3.3.3.tigcc8/gcc/config/dbxcoff.h	Thu Feb 19 21:20:02 2004
+@@ -53,13 +53,20 @@
+ 
+ /* Like block addresses, stabs line numbers are relative to the
+    current function.  */
++/* TIGCC Patch: We don't want COFF line numbers to be function-relative.
++   That's why we write '.ln LINE'. This will break support for existing
++   debuggers, but there are none for TIGCC. The line numbers can be
++   extracted from the .s file, plus they are passed on to the object file
++   symbol table. */
+ 
+ #undef ASM_OUTPUT_SOURCE_LINE
+ #define ASM_OUTPUT_SOURCE_LINE(FILE, LINE)			\
+ { if (write_symbols == SDB_DEBUG) {				\
+     fprintf ((FILE), "\t.ln\t%d\n",				\
+-	     ((sdb_begin_function_line > -1)			\
+-	      ? (LINE) - sdb_begin_function_line : 1));		\
++	     TARGET_COFFABSLINES				\
++	      ? (LINE)						\
++	      : ((sdb_begin_function_line > -1)			\
++	       ? (LINE) - sdb_begin_function_line : 1));	\
+   } else if (write_symbols == DBX_DEBUG) {			\
+     static int sym_lineno = 1;					\
+     char buffer[256];						\
+diff -Naur gcc-3.3.3.orig/gcc/config/m68k/m68k-coff.h gcc-3.3.3.tigcc8/gcc/config/m68k/m68k-coff.h
+--- gcc-3.3.3.orig/gcc/config/m68k/m68k-coff.h	Fri Sep  3 19:10:48 1999
++++ gcc-3.3.3.tigcc8/gcc/config/m68k/m68k-coff.h	Thu Feb 19 21:20:02 2004
+@@ -24,8 +24,16 @@
+ #define  USE_GAS
+ #endif
+ 
++/* Define the appropriate flags for the TI's architecture */
++
++#undef TARGET_CPU_DEFAULT
++#define TARGET_CPU_DEFAULT M68K_CPU_m68000
++
++#undef TARGET_DEFAULT
++#define TARGET_DEFAULT ((TARGET_CPU_DEFAULT >> 4) | MASK_SHORT | MASK_TIOS | MASK_MERGE_SECTIONS)
++
+ #include "m68k/m68k-none.h"
+-#include "m68k/m68kemb.h"
+ #include "m68k/coff.h"
++#include "m68k/m68k-ti.h"
+ 
+ /* end of m68k-coff.h */
+diff -Naur gcc-3.3.3.orig/gcc/config/m68k/m68k-protos.h gcc-3.3.3.tigcc8/gcc/config/m68k/m68k-protos.h
+--- gcc-3.3.3.orig/gcc/config/m68k/m68k-protos.h	Mon Oct 21 00:37:10 2002
++++ gcc-3.3.3.tigcc8/gcc/config/m68k/m68k-protos.h	Sun Feb 22 04:44:16 2004
+@@ -61,6 +61,8 @@
+ extern int nonimmediate_src_operand PARAMS ((rtx, enum machine_mode));
+ extern int memory_src_operand PARAMS ((rtx, enum machine_mode));
+ extern int pcrel_address PARAMS ((rtx, enum machine_mode));
++/* (TIGCC 20040222) used in the indirect_jump pattern -- Kevin Kofler */
++extern int extended_address_operand PARAMS ((rtx, enum machine_mode));
+ extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx));
+ #endif /* RTX_CODE */
+ 
+diff -Naur gcc-3.3.3.orig/gcc/config/m68k/m68k-ti.h gcc-3.3.3.tigcc8/gcc/config/m68k/m68k-ti.h
+--- gcc-3.3.3.orig/gcc/config/m68k/m68k-ti.h	Thu Jan  1 01:00:00 1970
++++ gcc-3.3.3.tigcc8/gcc/config/m68k/m68k-ti.h	Sat Jun 19 16:06:24 2004
+@@ -0,0 +1,225 @@
++/* Definitions of target machine for GNU compiler.
++   TI-68k architecture (68000),
++   COFF object files and debugging version.
++   Derived in part from m68kemb.h and other files.
++   Copyright (C) 1994 Free Software Foundation, Inc.
++   Copyright (C) 2000 mmu_man (François Revol)
++   (Modified by Sebastian Reichelt for the Windows release of TIGCC)
++ 
++This file is part of TIGCC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++/* Include special SMAP II BCD floating point support */
++#include <smapbcd.h>
++
++/* Define the output of the target version */
++
++#undef TARGET_VERSION
++#define TARGET_VERSION fprintf (stderr, " (MC68000 TI with COFF output)");
++
++/* Pass the right values to functions whose prototypes contain "char"
++   or "short". */
++
++#undef PROMOTE_PROTOTYPES
++
++/* Even if we compile with -mlong, we want only 16-bit alignment. */
++
++#undef PARM_BOUNDARY
++#define PARM_BOUNDARY 16
++
++/* Don't default to pcc-struct-return, so that we can return small
++   structures and unions in registers, which is slightly more
++   efficient. There are probably no TIOS routines returning structs;
++   if there are, the appropriate program will have to be compiled
++   with the "-fpcc-struct-return" option. But that option will cause
++   problems with ROM_CALLs returning a HSym, which is defined as a
++   structure in TIGCC.  */
++
++#undef DEFAULT_PCC_STRUCT_RETURN
++#define DEFAULT_PCC_STRUCT_RETURN 0
++
++/* In order for bitfields to work on a 68000, or with -mnobitfield, we must
++   define either PCC_BITFIELD_TYPE_MATTERS or STRUCTURE_SIZE_BOUNDARY.
++   Defining STRUCTURE_SIZE_BOUNDARY results in structure packing problems,
++   so we define PCC_BITFIELD_TYPE_MATTERS.  */
++
++#define PCC_BITFIELD_TYPE_MATTERS 1
++
++/* Undefine PCC_STATIC_STRUCT_RETURN so that we get a re-entrant
++   calling convention (whatever that means).  */
++
++#undef PCC_STATIC_STRUCT_RETURN
++
++/* Define how to generate (in the callee) the output value of a
++   function and how to find (in the caller) the value returned by a
++   function. VALTYPE is the data type of the value (as a tree). If
++   the precise function being called is known, FUNC is its
++   FUNCTION_DECL; otherwise, FUNC is 0. When calling TIOS functions,
++   find the result in d0 or a0 as appropriate. */
++ 
++#undef FUNCTION_VALUE
++#define FUNCTION_VALUE(VALTYPE, FUNC) \
++	(((TARGET_TIOS) && (POINTER_TYPE_P (VALTYPE))) \
++	? gen_rtx_REG (TYPE_MODE (VALTYPE), 8) \
++	: LIBCALL_VALUE (TYPE_MODE (VALTYPE)))
++
++/* Define how to find a library call return value. Usually the value will be
++   in d0 (thru d1 or d2), but floats should be assumed to be returned in a
++   stack frame. This happens automatically if the specified register (d1 in
++   this case) is not a possible register for returning the value, because
++   floats take up 3 registers. Never use direct floats if d3 is clobbered
++   by function calls. */
++
++#undef LIBCALL_VALUE
++#define LIBCALL_VALUE(MODE) \
++	(((TARGET_DIRECTFLOAT) && ((MODE) == BFmode)) \
++	? gen_rtx_REG (MODE, 1) \
++	: gen_rtx_REG (MODE, 0))
++
++/* 1 if N is a possible register number for a function value. For
++   calling TIOS functions, allow a0 in addition to d0 (see above). */
++
++#undef FUNCTION_VALUE_REGNO_P
++#define FUNCTION_VALUE_REGNO_P(N) \
++	(((N) == 0) || (TARGET_TIOS && ((N) == 8)) || (TARGET_DIRECTFLOAT && ((N) == 1)))
++
++/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
++   more than one register (see above). */
++
++#undef NEEDS_UNTYPED_CALL
++#define NEEDS_UNTYPED_CALL (TARGET_TIOS || TARGET_DIRECTFLOAT)
++
++/* This says how to output an assembler line
++   to define a global common symbol. */
++
++#undef ASM_OUTPUT_COMMON
++#define ASM_OUTPUT_COMMON(FILE,NAME,SIZE,ROUNDED) \
++do { \
++	if (TARGET_NO_BSS && ((NAME) [0] != '_')) \
++	{ \
++		long i; \
++		fputs (".globl ", (FILE)); \
++		assemble_name ((FILE), (NAME)); \
++		fputs ("\n\t.even\n", (FILE)); \
++		assemble_name ((FILE), (NAME)); \
++		fputs (":\n", (FILE)); \
++		fprintf ((FILE), "\t.space %u\n", (ROUNDED)); \
++		fputs ("\t.even\n", (FILE)); \
++	} \
++	else \
++	{ \
++		fputs (".comm ", (FILE)); \
++		assemble_name ((FILE), (NAME)); \
++		fprintf ((FILE), ",%u\n", (ROUNDED)); \
++	} \
++} while (0)
++
++/* This says how to output an assembler line
++   to define a local common symbol. */
++
++#undef ASM_OUTPUT_LOCAL
++#define ASM_OUTPUT_LOCAL(FILE,NAME,SIZE,ROUNDED) \
++do { \
++	if (TARGET_NO_BSS) \
++	{ \
++		long i; \
++		fputs ("\t.even\n", (FILE)); \
++		assemble_name ((FILE), (NAME)); \
++		fputs (":\n", (FILE)); \
++		fprintf ((FILE), "\t.space %u\n", (ROUNDED)); \
++		fputs ("\t.even\n", (FILE)); \
++	} \
++	else \
++	{ \
++		fputs (".lcomm ", (FILE)); \
++		assemble_name ((FILE), (NAME)); \
++		fprintf ((FILE), ",%u\n", (ROUNDED)); \
++	} \
++} while (0)
++
++/* If TARGET_MERGE_SECTIONS is set (on by default): if TARGET_MERGE_TO_DATA is
++   set, only use data sections, otherwise only use text sections. Both code and
++   data in RAM programs on a TI-89/92+/V200 are always writable; that's why it
++   does not make sense to have different data and text sections.
++   Those cannot be set to an empty string, since a number may follow, etc.
++   Anyway, better more than less. */
++
++#undef TEXT_SECTION_ASM_OP
++#define TEXT_SECTION_ASM_OP ((TARGET_MERGE_SECTIONS && TARGET_MERGE_TO_DATA)? \
++                             "\t.data":"\t.text")
++
++#undef DATA_SECTION_ASM_OP
++#define DATA_SECTION_ASM_OP ((TARGET_MERGE_SECTIONS && !TARGET_MERGE_TO_DATA)? \
++                             "\t.text":"\t.data")
++
++/* If TARGET_NO_BSS is set (off by default), use the data section here.
++   Otherwise use the BSS section. */
++
++#undef BSS_SECTION_ASM_OP
++#define BSS_SECTION_ASM_OP (TARGET_NO_BSS?DATA_SECTION_ASM_OP:"\t.section .bss")
++
++/* When not merging sections, put read-only data into .data unless
++   TARGET_RODATA_TO_TEXT is set. But jump tables do NOT qualify for going into
++   the data section! */
++#define READONLY_DATA_SECTION() (TARGET_RODATA_TO_TEXT ? text_section() \
++                                                       : data_section())
++#define JUMP_TABLES_IN_TEXT_SECTION 1
++
++/* If TARGET_MERGE_SECTIONS is set (on by default), we need an explicit '.text'
++   or '.data' (depending on TARGET_MERGE_TO_DATA) statement at the beginning of
++   the file. */
++
++#undef ASM_FILE_START
++#define ASM_FILE_START(FILE) \
++do { \
++	output_file_directive ((FILE), main_input_filename); \
++	fprintf ((FILE), "#NO_APP\n"); \
++	if (TARGET_REG_RELATIVE) \
++		fprintf ((FILE), "\t.set __relation,__ld_entry_point_plus_0x8000\n\t.xdef __ref_all___reg_relative_%s\n", TARGET_RELATION_REG); \
++	fprintf ((FILE), (TARGET_MERGE_SECTIONS?(TARGET_MERGE_TO_DATA?"\t.data\ntigcc_compiled.:\n":"\t.text\ntigcc_compiled.:\n"):"tigcc_compiled.:\n")); \
++} while (0)
++
++/* Define "__INT_SHORT__" if short ints are set, e.g. if the "-mlong" switch
++   is not used. This is necessary for the TIGCC Library, since INT_MAX and
++   others need to be constants. */
++
++#undef CPP_SUBTARGET_SPEC
++#if (defined(__CYGWIN__) || defined(__WIN32__))
++#define CPP_SUBTARGET_SPEC "-D__TIGCC_ENV__ -D__TIGCC_WIN_ENV__ %{!mlong:%{!mnoshort:%{!mno-short:-D__INT_SHORT__ }}}"
++#else
++#define CPP_SUBTARGET_SPEC "-D__TIGCC_ENV__ %{!mlong:%{!mnoshort:%{!mno-short:-D__INT_SHORT__ }}}"
++#endif
++
++/* Trampolines are code on the stack, so we need to add 0x40000 to their address
++   for it to work on a TI-89/92+/V200 HW2. On HW3, we should NOT add that
++   address. Moreover, EXECUTE_IN_GHOST_SPACE is required for it to work
++   correctly. Therefore, I am emitting a libcall and letting TIGCCLIB worry
++   about the details.
++   (code partially lifted from gcc/config/sh/sh.h) */
++#define TRAMPOLINE_ADJUST_ADDRESS(TRAMP) do \
++{ \
++  (TRAMP) = expand_simple_binop (Pmode, PLUS, (TRAMP), \
++                                 emit_library_call_value (gen_rtx_SYMBOL_REF (\
++                                                           Pmode, \
++                                                           "__trampoline_offset"), \
++                                                          NULL_RTX, LCT_CONST, \
++                                                          Pmode, 0), \
++                                 gen_reg_rtx (Pmode), 0, \
++                                 OPTAB_LIB_WIDEN); \
++} while (0)
++
++/* end of m68k-ti.h */
+diff -Naur gcc-3.3.3.orig/gcc/config/m68k/m68k.c gcc-3.3.3.tigcc8/gcc/config/m68k/m68k.c
+--- gcc-3.3.3.orig/gcc/config/m68k/m68k.c	Sat Jun 28 02:27:04 2003
++++ gcc-3.3.3.tigcc8/gcc/config/m68k/m68k.c	Sat Sep 25 00:28:06 2004
+@@ -43,6 +43,9 @@
+ /* Needed for use_return_insn.  */
+ #include "flags.h"
+ 
++/* TIGCC register for reg-relative code.  */
++char TARGET_RELATION_REG[10] = "a4";
++
+ #ifdef SUPPORT_SUN_FPA
+ 
+ /* Index into this array by (register number >> 3) to find the
+@@ -68,6 +71,12 @@
+ static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ 					  HOST_WIDE_INT, tree));
+ static int m68k_save_reg PARAMS ((unsigned int));
++
++static int comp_m68k_type_attributes PARAMS ((tree, tree));
++static int comp_amigaos_type_attributes PARAMS ((tree, tree));
++const struct attribute_spec m68k_attribute_table[];
++static tree m68k_handle_stkparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
++static tree m68k_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
+ 
+ 
+ /* Alignment to use for loops and jumps */
+@@ -77,6 +86,8 @@
+ const char *m68k_align_jumps_string;
+ /* Specify power of two alignment used for functions.  */
+ const char *m68k_align_funcs_string;
++/* Specify number of registers for integer, pointer and float arguments.  */
++const char *m68k_regparm_string;
+ 
+ /* Specify power of two alignment used for loops.  */
+ int m68k_align_loops;
+@@ -84,6 +95,8 @@
+ int m68k_align_jumps;
+ /* Specify power of two alignment used for functions.  */
+ int m68k_align_funcs;
++/* Specify number of registers for integer, pointer and float arguments.  */
++int m68k_regparm;
+ 
+ /* Nonzero if the last compare/test insn had FP operands.  The
+    sCC expanders peek at this to determine what to do for the
+@@ -91,6 +104,11 @@
+ int m68k_last_compare_had_fp_operands;
+ 
+ /* Initialize the GCC target structure.  */
++#undef TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE m68k_attribute_table
++
++#undef TARGET_COMP_TYPE_ATTRIBUTES
++#define TARGET_COMP_TYPE_ATTRIBUTES comp_amigaos_type_attributes
+ 
+ #if INT_OP_GROUP == INT_OP_DOT_WORD
+ #undef TARGET_ASM_ALIGNED_HI_OP
+@@ -173,6 +191,20 @@
+ 
+   /* Validate -malign-functions= value, or provide default */
+   m68k_align_funcs = def_align;
++ 
++   /* Validate -mregparm and -mregparm= value.  */
++   if (m68k_regparm_string)
++     {
++       m68k_regparm = atoi (m68k_regparm_string);
++       if (m68k_regparm < 1 || m68k_regparm > M68K_MAX_REGPARM)
++ 	error ("-mregparm=%d is not between 1 and %d",
++ 	       m68k_regparm, M68K_MAX_REGPARM);
++       target_flags |= MASK_REGPARM;
++     }
++   else
++     if (TARGET_REGPARM)
++       m68k_regparm = M68K_DEFAULT_REGPARM;
++
+   if (m68k_align_funcs_string)
+     {
+       i = atoi (m68k_align_funcs_string);
+@@ -204,8 +236,10 @@
+ 
+   SUBTARGET_OVERRIDE_OPTIONS;
+ 
++#if 0 /* (TIGCC) We are not using ANY flavor of XFmode. */
+   /* Tell the compiler which flavor of XFmode we're using.  */
+   real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;
++#endif /* 0 */
+ }
+ 
+ /* Return 1 if we need to save REGNO.  */
+@@ -1736,7 +1770,14 @@
+ #else
+       return "moveq %1,%0";
+ #endif
++/* (TIGCC 20040211) Backport from mainline:
++2004-01-11  Andreas Schwab  <schwab@suse.de>
++
++	* config/m68k/m68k.c (output_move_const_into_data_reg): Clear cc
++	status for NOTB/NOTW/NEGW methods.
++-- Kevin Kofler */
+     case NOTB :
++      CC_STATUS_INIT;
+       operands[1] = GEN_INT (i ^ 0xff);
+ #if defined (MOTOROLA) && !defined (CRDS)
+       return "moveq%.l %1,%0\n\tnot%.b %0";
+@@ -1744,6 +1785,7 @@
+       return "moveq %1,%0\n\tnot%.b %0";
+ #endif	 
+     case NOTW :
++      CC_STATUS_INIT;
+       operands[1] = GEN_INT (i ^ 0xffff);
+ #if defined (MOTOROLA) && !defined (CRDS)
+       return "moveq%.l %1,%0\n\tnot%.w %0";
+@@ -1751,6 +1793,7 @@
+       return "moveq %1,%0\n\tnot%.w %0";
+ #endif	 
+     case NEGW :
++      CC_STATUS_INIT;
+ #if defined (MOTOROLA) && !defined (CRDS)
+       return "moveq%.l %#-128,%0\n\tneg%.w %0";
+ #else
+@@ -1774,6 +1817,25 @@
+     }
+ }
+ 
++char *
++output_move_himode_const (operands)
++     rtx *operands;
++{
++  if (operands[1] == const0_rtx
++      && (DATA_REG_P (operands[0])
++	  || GET_CODE (operands[0]) == MEM)
++      /* clr insns on 68000 read before writing.
++	 This isn't so on the 68010, but we have no TARGET_68010.  */
++      && ((TARGET_68020 || TARGET_5200)
++	  || !(GET_CODE (operands[0]) == MEM
++	       && MEM_VOLATILE_P (operands[0]))))
++    return "clr%.w %0";
++  else if (operands[1] == const0_rtx
++	   && ADDRESS_REG_P (operands[0]))
++    return "sub%.w %0,%0";
++  return "move%.w %1,%0";
++}
++
+ const char *
+ output_move_simode_const (operands)
+      rtx *operands;
+@@ -1995,6 +2057,15 @@
+    for moving operands[1] into operands[0] as a fullword.  */
+ 
+ static const char *
++halfsinglemove_string (operands)
++     rtx *operands;
++{
++  if (GET_CODE (operands[1]) == CONST_INT)
++    return output_move_himode_const (operands);
++  return "move%.w %1,%0";
++}
++
++static const char *
+ singlemove_string (operands)
+      rtx *operands;
+ {
+@@ -2075,10 +2146,14 @@
+       operands[0] = XEXP (XEXP (operands[0], 0), 0);
+       if (size == 12)
+         output_asm_insn ("sub%.l %#12,%0", operands);
++      else if (size == 10)
++        output_asm_insn ("sub%.l %#10,%0", operands);
+       else
+         output_asm_insn ("subq%.l %#8,%0", operands);
+-      if (GET_MODE (operands[1]) == XFmode)
++      if (GET_MODE (operands[0]) == XFmode)
+ 	operands[0] = gen_rtx_MEM (XFmode, operands[0]);
++      else if (GET_MODE (operands[0]) == BFmode)
++	operands[0] = gen_rtx_MEM (BFmode, operands[0]);
+       else if (GET_MODE (operands[0]) == DFmode)
+ 	operands[0] = gen_rtx_MEM (DFmode, operands[0]);
+       else
+@@ -2090,10 +2165,14 @@
+       operands[1] = XEXP (XEXP (operands[1], 0), 0);
+       if (size == 12)
+         output_asm_insn ("sub%.l %#12,%1", operands);
++      else if (size == 10)
++        output_asm_insn ("sub%.l %#10,%1", operands);
+       else
+         output_asm_insn ("subq%.l %#8,%1", operands);
+       if (GET_MODE (operands[1]) == XFmode)
+ 	operands[1] = gen_rtx_MEM (XFmode, operands[1]);
++      else if (GET_MODE (operands[1]) == BFmode)
++	operands[1] = gen_rtx_MEM (BFmode, operands[1]);
+       else if (GET_MODE (operands[1]) == DFmode)
+ 	operands[1] = gen_rtx_MEM (DFmode, operands[1]);
+       else
+@@ -2129,7 +2208,7 @@
+       else if (optype0 == OFFSOP)
+ 	{
+ 	  middlehalf[0] = adjust_address (operands[0], SImode, 4);
+-	  latehalf[0] = adjust_address (operands[0], SImode, size - 4);
++	  latehalf[0] = adjust_address (operands[0], SImode, 8);
+ 	}
+       else
+ 	{
+@@ -2145,7 +2224,7 @@
+       else if (optype1 == OFFSOP)
+ 	{
+ 	  middlehalf[1] = adjust_address (operands[1], SImode, 4);
+-	  latehalf[1] = adjust_address (operands[1], SImode, size - 4);
++	  latehalf[1] = adjust_address (operands[1], SImode, 8);
+ 	}
+       else if (optype1 == CNSTOP)
+ 	{
+@@ -2177,8 +2256,66 @@
+ 	  latehalf[1] = operands[1];
+ 	}
+     }
+-  else
+-    /* size is not 12: */
++  else if (size == 10)
++    {
++      if (optype0 == REGOP)
++	{
++	  latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 2);
++	  middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
++	}
++      else if (optype0 == OFFSOP)
++	{
++	  middlehalf[0] = adjust_address (operands[0], SImode, 4);
++	  latehalf[0] = adjust_address (operands[0], SImode, 8);
++	}
++      else
++	{
++	  middlehalf[0] = operands[0];
++	  latehalf[0] = operands[0];
++	}
++
++      if (optype1 == REGOP)
++	{
++	  latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 2);
++	  middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
++	}
++      else if (optype1 == OFFSOP)
++	{
++	  middlehalf[1] = adjust_address (operands[1], SImode, 4);
++	  latehalf[1] = adjust_address (operands[1], SImode, 8);
++	}
++      else if (optype1 == CNSTOP)
++	{
++	  if (GET_CODE (operands[1]) == CONST_DOUBLE)
++	    {
++	      REAL_VALUE_TYPE r;
++	      long l[3];
++
++	      abort ();
++	      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
++	      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
++	      operands[1] = GEN_INT (l[0]);
++	      middlehalf[1] = GEN_INT (l[1]);
++	      latehalf[1] = GEN_INT (l[2]);
++	    }
++	  else if (CONSTANT_P (operands[1]))
++	    {
++	      /* actually, no non-CONST_DOUBLE constant should ever
++		 appear here.  */
++	      abort ();
++	      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
++		latehalf[1] = constm1_rtx;
++	      else
++		latehalf[1] = const0_rtx;
++	    }
++	}
++      else
++	{
++	  middlehalf[1] = operands[1];
++	  latehalf[1] = operands[1];
++	}
++    }
++  else    /* size is neither 12 or 10: */
+     {
+       if (optype0 == REGOP)
+ 	latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+@@ -2203,7 +2340,16 @@
+   if (optype0 == PUSHOP
+       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
++  {
++    if (size==10) {
++      /* (TIGCC 20040219) The above is not quite right for size==10. What we
++         have to do here is: (1) move.w operands[1]+8,-(%sp);
++         (2) move.l operands[1]+6,-(%sp); (3) move.l operands[1]+6,-(%sp).
++         -- Kevin Kofler */
++      operands[1] = middlehalf[1] = adjust_address (operands[1], SImode, 6);
++    } else
+     operands[1] = middlehalf[1] = latehalf[1];
++  }
+ 
+   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
+      if the upper part of reg N does not appear in the MEM, arrange to
+@@ -2231,6 +2377,12 @@
+ 	      middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
+ 	      latehalf[1] = adjust_address (operands[1], DImode, size - 4);
+ 	    }
++	  else if( GET_MODE (operands[1]) == BFmode )
++	    {
++	      operands[1] = gen_rtx_MEM (BFmode, latehalf[0]);
++	      middlehalf[1] = adjust_address (operands[1], DImode, 4);
++	      latehalf[1] = adjust_address (operands[1], DImode, 8);
++	    }
+ 	  else
+ 	    {
+ 	      operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
+@@ -2261,6 +2413,30 @@
+ 	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ 	  return "";
+ 	}
++      else if (size == 10
++	       && reg_overlap_mentioned_p (middlehalf[0],
++					   XEXP (operands[1], 0)))
++	{
++	  /* Check for two regs used by both source and dest.
++	     Note that this can't happen if the dest is all data regs.
++	     It can happen if the dest is d6, d7, a0.
++	     But in that case, latehalf is an addr reg, so
++	     the code at compadr does ok.  */
++
++	  if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
++	      || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
++	    goto compadr;
++
++	  /* JRV says this can't happen: */
++	  if (addreg0 || addreg1)
++	    abort ();
++
++	  /* Only the middle reg conflicts; simply put it last. */
++	  output_asm_insn (singlemove_string (operands), operands);
++	  output_asm_insn (halfsinglemove_string (latehalf), latehalf);
++	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
++	  return "";
++	}
+       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
+ 	/* If the low half of dest is mentioned in the source memory
+ 	   address, the arrange to emit the move late half first.  */
+@@ -2284,21 +2460,24 @@
+       /* Make any unoffsettable addresses point at high-numbered word.  */
+       if (addreg0)
+ 	{
+-	  if (size == 12)
++	  if (size == 12 || size == 10)
+ 	    output_asm_insn ("addq%.l %#8,%0", &addreg0);
+ 	  else
+ 	    output_asm_insn ("addq%.l %#4,%0", &addreg0);
+ 	}
+       if (addreg1)
+ 	{
+-	  if (size == 12)
++	  if (size == 12 || size == 10)
+ 	    output_asm_insn ("addq%.l %#8,%0", &addreg1);
+ 	  else
+ 	    output_asm_insn ("addq%.l %#4,%0", &addreg1);
+ 	}
+ 
+       /* Do that word.  */
+-      output_asm_insn (singlemove_string (latehalf), latehalf);
++      if (size == 10)
++        output_asm_insn (halfsinglemove_string (latehalf), latehalf);
++      else
++        output_asm_insn (singlemove_string (latehalf), latehalf);
+ 
+       /* Undo the adds we just did.  */
+       if (addreg0)
+@@ -2306,7 +2485,7 @@
+       if (addreg1)
+ 	output_asm_insn ("subq%.l %#4,%0", &addreg1);
+ 
+-      if (size == 12)
++      if (size == 12 || size == 10)
+ 	{
+ 	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ 	  if (addreg0)
+@@ -2324,7 +2503,7 @@
+   output_asm_insn (singlemove_string (operands), operands);
+ 
+   /* Do the middle one of the three words for long double */
+-  if (size == 12)
++  if (size == 12 || size == 10)
+     {
+       if (addreg0)
+ 	output_asm_insn ("addq%.l %#4,%0", &addreg0);
+@@ -2341,19 +2520,22 @@
+     output_asm_insn ("addq%.l %#4,%0", &addreg1);
+ 
+   /* Do that word.  */
+-  output_asm_insn (singlemove_string (latehalf), latehalf);
++  if (size == 10)
++    output_asm_insn (halfsinglemove_string (latehalf), latehalf);
++  else
++    output_asm_insn (singlemove_string (latehalf), latehalf);
+ 
+   /* Undo the adds we just did.  */
+   if (addreg0)
+     {
+-      if (size == 12)
++      if (size == 12 || size == 10)
+         output_asm_insn ("subq%.l %#8,%0", &addreg0);
+       else
+         output_asm_insn ("subq%.l %#4,%0", &addreg0);
+     }
+   if (addreg1)
+     {
+-      if (size == 12)
++      if (size == 12 || size == 10)
+         output_asm_insn ("subq%.l %#8,%0", &addreg1);
+       else
+         output_asm_insn ("subq%.l %#4,%0", &addreg1);
+@@ -2762,6 +2944,8 @@
+ floating_exact_log2 (x)
+      rtx x;
+ {
++abort();
++#if 0
+   REAL_VALUE_TYPE r, r1;
+   int exp;
+ 
+@@ -2776,6 +2960,7 @@
+     return exp;
+ 
+   return 0;
++#endif /* 0 */
+ }
+ 
+ #ifdef SUPPORT_SUN_FPA
+@@ -2986,6 +3171,8 @@
+        CONST_DOUBLE's as SunFPA constant RAM registers if
+        possible, so it should not be used except for the SunFPA.
+ 
++(TIGCC 20040222) 'A' like 'o', but for addresses.
++
+    */
+ 
+ void
+@@ -3062,6 +3249,14 @@
+ 	abort ();
+       output_addr_const (file, XEXP (op, 0));
+     }
++  else if (letter == 'A') /* (TIGCC 20040222) */
++    {
++      if (TARGET_PCREL) {
++        target_flags&=~MASK_PCREL; /* ugly hack, but works */
++        print_operand_address(file,op);
++        target_flags|=MASK_PCREL;
++      } else print_operand_address(file,op);
++    }
+   else if (GET_CODE (op) == REG)
+     {
+ #ifdef SUPPORT_SUN_FPA
+@@ -3086,6 +3281,15 @@
+   else if (GET_CODE (op) == MEM)
+     {
+       output_address (XEXP (op, 0));
++      /* TIGCC Patch: This is a very bad try to implement addresses relative to a register.
++         Julien Muchembled says this should work.
++         At least it should if only one file is used.
++         (TIGCC 20040808) Added CONST. A MEM(CONST) is used for sym+const addressing. This
++                          needs to be made reg-relative too. -- Kevin Kofler  */
++      if (TARGET_REG_RELATIVE && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF || GET_CODE (XEXP (op, 0)) == CODE_LABEL || GET_CODE (XEXP (op, 0)) == CONST))
++        fprintf (file, "-__relation(%%%s)", TARGET_RELATION_REG);
++      else
++	{
+       if (letter == 'd' && ! TARGET_68020
+ 	  && CONSTANT_ADDRESS_P (XEXP (op, 0))
+ 	  && !(GET_CODE (XEXP (op, 0)) == CONST_INT
+@@ -3098,6 +3302,7 @@
+ 	  fprintf (file, ":l");
+ #endif
+ 	}
++	}
+     }
+ #ifdef SUPPORT_SUN_FPA
+   else if ((letter == 'y' || letter == 'w')
+@@ -3107,6 +3312,7 @@
+       fprintf (file, "%%%d", i & 0x1ff);
+     }
+ #endif
++#if 0
+   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
+     {
+       REAL_VALUE_TYPE r;
+@@ -3125,6 +3331,7 @@
+       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
+     }
++#endif /* 0 */
+   else
+     {
+       /* Use `print_operand_address' instead of `output_addr_const'
+@@ -3564,7 +3771,7 @@
+ 	  && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
+ #else
+   return (GET_CODE (op) == CONST_INT
+-	  || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
++	  && INTVAL (op) >= 0);
+ #endif
+ }
+ 
+@@ -3709,13 +3916,317 @@
+ 	  || GET_CODE (op) == CONST);
+ }
+ 
++/* (TIGCC 20040222) This function is used to allow straight labels in the
++                    indirect_jump pattern. -- Kevin Kofler */
++int
++extended_address_operand (op, mode)
++     rtx op;
++     enum machine_mode mode;
++{
++  if (TARGET_PCREL && CONSTANT_ADDRESS_P (op))
++    return 1;
++  return address_operand (op, mode);
++}
++
++/* Argument-passing support functions.  */
++
++/* Initialize a variable CUM of type CUMULATIVE_ARGS
++   for a call to a function whose data type is FNTYPE.
++   For a library call, FNTYPE is 0.  */
++
++void
++m68k_init_cumulative_args (cum, fntype)
++     CUMULATIVE_ARGS *cum;
++     tree fntype;
++{
++  cum->last_arg_reg = -1;
++  cum->regs_already_used = 0;
++  if (fntype)
++    {
++      if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES (fntype)))
++	cum->num_of_regs = 0;
++      else
++	{
++	  tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
++	  if (ratree)
++	    {
++	      cum->num_of_regs = m68k_regparm ? m68k_regparm
++					      : M68K_DEFAULT_REGPARM;
++	      if (TREE_VALUE (ratree)
++		  && TREE_CODE (TREE_VALUE (ratree)) == TREE_LIST)
++		{
++		  tree num_of_regs = TREE_VALUE (TREE_VALUE (ratree));
++		  cum->num_of_regs =
++		    num_of_regs ? TREE_INT_CST_LOW (num_of_regs) :
++		      (m68k_regparm ? m68k_regparm : M68K_DEFAULT_REGPARM);
++		}
++	    }
++	  else
++	    cum->num_of_regs = m68k_regparm;
++	}
++    }
++  else /* Libcall.  */
++    cum->num_of_regs = 0;
++
++  if (cum->num_of_regs)
++    {
++      /* If this is a vararg call, put all arguments on stack.  */
++      tree param, next_param;
++      for (param = TYPE_ARG_TYPES (fntype); param; param = next_param)
++	{
++	  next_param = TREE_CHAIN (param);
++	  if (!next_param && TREE_VALUE (param) != void_type_node)
++	    cum->num_of_regs = 0;
++	}
++    }
++
++#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (STRUCT_VALUE_REGNUM)
++  /* If return value is a structure, and we pass the buffer address in a
++     register, we can't use this register for our own purposes.
++     FIXME: Something similar would be useful for static chain.  */
++  if (fntype && aggregate_value_p (TREE_TYPE (fntype)))
++    cum->regs_already_used |= (1 << STRUCT_VALUE_REGNUM);
++#endif
++}
++
++/* Update the data in CUM to advance over an argument.  */
++
++void
++m68k_function_arg_advance (cum)
++     CUMULATIVE_ARGS *cum;
++{
++  if (cum->last_arg_reg != -1)
++    {
++      int count;
++      for (count = 0; count < cum->last_arg_len; count++)
++	cum->regs_already_used |= (1 << (cum->last_arg_reg + count));
++      cum->last_arg_reg = -1;
++    }
++}
++
++/* Define where to put the arguments to a function.
++   Value is zero to push the argument on the stack,
++   or a hard register in which to store the argument.
++
++   MODE is the argument's machine mode.
++   TYPE is the data type of the argument (as a tree).
++   This is null for libcalls where that information may
++    not be available.
++   CUM is a variable of type CUMULATIVE_ARGS which gives info about
++    the preceding args and about the function being called.  */
++
++struct rtx_def *
++m68k_function_arg (cum, mode, type)
++     CUMULATIVE_ARGS *cum;
++     enum machine_mode mode;
++     tree type;
++{
++  if (cum->num_of_regs)
++    {
++      int regbegin = -1, altregbegin = -1, len;
++
++      /* FIXME: The last condition below is a workaround for a bug.  */
++      if (TARGET_68881 && FLOAT_MODE_P (mode) &&
++	  GET_MODE_UNIT_SIZE (mode) <= 12 &&
++	  (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode))
++	{
++	  regbegin = 16; /* FPx */
++	  len = GET_MODE_NUNITS (mode);
++	}
++      /* FIXME: Two last conditions below are workarounds for bugs.  */
++      else if (INTEGRAL_MODE_P (mode) && mode !=CQImode && mode != CHImode)
++	{
++	  if (POINTER_TYPE_P (type))
++	    regbegin = 8; /* Ax */
++	  else
++	    regbegin = 0; /* Dx */
++	  altregbegin = 8 - regbegin;
++	  len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
++	}
++
++      if (regbegin != -1)
++	{
++	  int reg;
++	  long mask;
++
++look_for_reg:
++	  mask = 1 << regbegin;
++	  for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1)
++	    if (!(cum->regs_already_used & mask))
++	      {
++		int end;
++		for (end = reg; end < cum->num_of_regs && end < reg + len;
++		     end++, mask <<= 1)
++		  if (cum->regs_already_used & mask)
++		    break;
++		if (end == reg + len)
++		  {
++		    cum->last_arg_reg = reg + regbegin;
++		    cum->last_arg_len = len;
++		    break;
++		  }
++	      }
++
++	  if (reg == cum->num_of_regs && altregbegin != -1)
++	    {
++	      regbegin = altregbegin;
++	      altregbegin = -1;
++	      goto look_for_reg;
++	    }
++	}
++
++      if (cum->last_arg_reg != -1)
++	return gen_rtx (REG, mode, cum->last_arg_reg);
++    }
++  return 0;
++}
++
++/* (TIGCC) Attributes support. */
++
++/* Table of valid machine attributes. */
++const struct attribute_spec m68k_attribute_table[] =
++{
++  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
++  /* The stkparm attribute means a function takes its parameters on the stack
++     (AMS calling convention). */
++  { "stkparm",   0, 0, false, true,  true,  m68k_handle_stkparm_attribute },
++  /* The regparm attribute means a function takes its parameters in registers.
++     Its optional argument specifies the maximum number of arguments to be
++     passed in each category of registers (data registers, address registers). */
++  { "regparm",   0, 1, false, true,  true,  m68k_handle_regparm_attribute },
++  /* The name NULL means the attribute list ends here. */
++  { NULL,        0, 0, false, false, false, NULL }
++};
++
++/* Handle a "stkparm" attribute;
++   arguments as in struct attribute_spec.handler. */
++static tree
++m68k_handle_stkparm_attribute (node, name, args, flags, no_add_attrs)
++     tree *node;
++     tree name;
++     tree args ATTRIBUTE_UNUSED;
++     int flags ATTRIBUTE_UNUSED;
++     bool *no_add_attrs;
++{
++  if (lookup_attribute ("regparm", TYPE_ATTRIBUTES (*node)))
++  {
++    error ("`regparm' and `stkparm' are mutually exclusive");
++    *no_add_attrs = true;
++  }
++
++  if (TREE_CODE (*node) != FUNCTION_TYPE
++      && TREE_CODE (*node) != METHOD_TYPE
++      && TREE_CODE (*node) != FIELD_DECL
++      && TREE_CODE (*node) != TYPE_DECL)
++    {
++      warning ("`%s' attribute only applies to functions",
++	       IDENTIFIER_POINTER (name));
++      *no_add_attrs = true;
++    }
++
++  return NULL_TREE;
++}
++
++/* Handle a "regparm" attribute;
++   arguments as in struct attribute_spec.handler. */
++static tree
++m68k_handle_regparm_attribute (node, name, args, flags, no_add_attrs)
++     tree *node;
++     tree name;
++     tree args;
++     int flags ATTRIBUTE_UNUSED;
++     bool *no_add_attrs;
++{
++  if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES (*node)))
++  {
++    error ("`regparm' and `stkparm' are mutually exclusive");
++    *no_add_attrs = true;
++  }
++
++  if (TREE_CODE (*node) != FUNCTION_TYPE
++      && TREE_CODE (*node) != METHOD_TYPE
++      && TREE_CODE (*node) != FIELD_DECL
++      && TREE_CODE (*node) != TYPE_DECL)
++    {
++      warning ("`%s' attribute only applies to functions",
++	       IDENTIFIER_POINTER (name));
++      *no_add_attrs = true;
++    }
++  else
++    {
++      /* 'regparm' accepts one optional argument - number of registers per
++         single class (data, address) that should be used to pass arguments. */
++      if (args && TREE_CODE (args) == TREE_LIST)
++      {
++        tree numofregs = TREE_VALUE (args);
++        if (numofregs)
++          if (TREE_CODE (numofregs) != INTEGER_CST
++              || TREE_INT_CST_HIGH (numofregs)
++              || TREE_INT_CST_LOW (numofregs) < 1
++              || TREE_INT_CST_LOW (numofregs) > M68K_MAX_REGPARM)
++          {
++            error ("invalid argument to `regparm' attribute");
++       	    *no_add_attrs = true;
++          }
++      }
++    }
++
++  return NULL_TREE;
++}
++
++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
++   one if they are compatible, and two if they are nearly compatible
++   (which causes a warning to be generated). */
++
++int
++comp_m68k_type_attributes (type1, type2)
++     tree type1, type2;
++{
++  /* Functions or methods are incompatible if they specify mutually
++     exclusive ways of passing arguments.  */
++  if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE)
++    {
++      tree arg1, arg2;
++      if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) !=
++	     !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2))
++	  || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) !=
++	     !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)))
++	return 0; /* 'regparm' and 'stkparm' are mutually exclusive.  */
++
++      arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1));
++      arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2));
++      if (arg1 && arg2)
++	{
++	  int num1 = 0, num2 = 0;
++	  if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST)
++	    {
++	      tree numofregs = TREE_VALUE (TREE_VALUE (arg1));
++	      if (numofregs)
++		num1 = TREE_INT_CST_LOW (numofregs);
++	    }
++	  if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST)
++	    {
++	      tree numofregs = TREE_VALUE (TREE_VALUE (arg2));
++	      if (numofregs)
++		num2 = TREE_INT_CST_LOW (numofregs);
++	    }
++	  if (num1 != num2)
++	    return 0; /* Different numbers, or no number in one type.  */
++	}
++    }
++  return 1;
++}
++
+ const char *
+ output_andsi3 (operands)
+      rtx *operands;
+ {
+   int logval;
+   if (GET_CODE (operands[2]) == CONST_INT
+-      && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
++/* (TIGCC 20040925) This is a backport of a 64-bit cross fix from mainline by
++   Andreas Schwab. As he says, "((HOST_WIDE_INT) -43691 | 0xffff) can never
++   equal 0xffffffff when HOST_WIDE_INT has more than 32 bits. -- Kevin Kofler */
++      && (INTVAL (operands[2]) | 0xffff) == -1
+       && (DATA_REG_P (operands[0])
+ 	  || offsettable_memref_p (operands[0]))
+       && !TARGET_5200)
+@@ -3831,13 +4342,28 @@
+      unsigned int flags;
+ {
+   char flagchar;
+-
+-  if (flags & SECTION_WRITE)
++  /* (TIGCC 20040725) Constant/string merging flags for TIGCC-extended COFF.
++                      SECTION_STRINGS is abused for the unaligned flag. */
++  const char *xflags = "";
++
++  /* (TIGCC 20040619) Handle BSS sections properly with -fdata-sections.
++                      -- Kevin Kofler*/
++  if ((flags & SECTION_BSS) && !TARGET_NO_BSS)
++    flagchar = 'b';
++  /* (TIGCC 20040620) Handle rodata sections properly with -fdata-sections.
++                      -- Kevin Kofler*/
++  else if ((flags & SECTION_WRITE)
++           || (!TARGET_RODATA_TO_TEXT && !(flags & SECTION_CODE)))
+     flagchar = 'd';
+   else
+     flagchar = 'x';
+ 
+-  fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
++  if (flags & SECTION_MERGE)
++    xflags = (flags & SECTION_STRINGS)?"mu":"m";
++  else if (flags & SECTION_STRINGS)
++    xflags = "u";
++
++  fprintf (asm_out_file, "\t.section\t%s,\"%c%s\"\n", name, flagchar, xflags);
+ }
+ 
+ #ifdef CTOR_LIST_BEGIN
+@@ -3900,7 +4426,7 @@
+   if (flag_pic)
+     {
+       if (TARGET_PCREL)
+-	fmt = "bra.l %o0";
++	fmt = "jra %o0"; /* (TIGCC 20040222) */
+       else
+ 	{
+ #ifdef MOTOROLA
+@@ -3937,3 +4463,105 @@
+ 
+   output_asm_insn (fmt, xops);
+ }
++
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++
++/* Initialize a variable CUM of type CUMULATIVE_ARGS
++   for a call to a function whose data type is FNTYPE.
++   For a library call, FNTYPE is 0.  */
++
++void
++amigaos_init_cumulative_args(CUMULATIVE_ARGS *cum, tree fntype)
++{
++  m68k_init_cumulative_args(cum, fntype);
++
++  if (fntype)
++    cum->formal_type=TYPE_ARG_TYPES(fntype);
++  else /* Call to compiler-support function. */
++    cum->formal_type=0;
++}
++
++/* Update the data in CUM to advance over an argument.  */
++
++void
++amigaos_function_arg_advance(CUMULATIVE_ARGS *cum)
++{
++  m68k_function_arg_advance(cum);
++
++  if (cum->formal_type)
++    cum->formal_type=TREE_CHAIN((tree)cum->formal_type);
++}
++
++/* A C expression that controls whether a function argument is passed
++   in a register, and which register. */
++
++struct rtx_def *
++amigaos_function_arg(CUMULATIVE_ARGS *cum, enum machine_mode mode,
++  tree type)
++{
++  tree asmtree;
++  if (cum->formal_type && TREE_VALUE((tree)cum->formal_type)
++      && (asmtree=lookup_attribute("asm",
++			TYPE_ATTRIBUTES(TREE_VALUE((tree)cum->formal_type)))))
++    {
++      int i;
++#if 0
++      /* See c-decl.c/push_parm_decl for an explanation why this doesn't work.
++       */
++      cum->last_arg_reg=TREE_INT_CST_LOW(TREE_VALUE(TREE_VALUE(asmtree)));
++#else
++      cum->last_arg_reg=TREE_INT_CST_LOW(TREE_VALUE(asmtree));
++#endif
++      cum->last_arg_len=HARD_REGNO_NREGS(cum->last_arg_reg, mode);
++
++      for (i=0; i<cum->last_arg_len; i++)
++	if (cum->regs_already_used & (1 << cum->last_arg_reg+i))
++	  {
++	    error("two parameters allocated for one register");
++	    break;
++	  }
++      return gen_rtx(REG, mode, cum->last_arg_reg);
++    }
++  else
++    return (struct rtx_def *)m68k_function_arg(cum, mode, type);
++}
++
++/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
++   one if they are compatible, and two if they are nearly compatible
++   (which causes a warning to be generated). */
++
++int
++comp_amigaos_type_attributes(tree type1, tree type2)
++{
++  int ret;
++  if ((ret=comp_m68k_type_attributes(type1, type2))!=1)
++    return ret;
++
++  /* Functions or methods are incompatible if they specify mutually exclusive
++     ways of passing arguments. */
++  if (TREE_CODE(type1)==FUNCTION_TYPE || TREE_CODE(type1)==METHOD_TYPE)
++    {
++      tree arg1, arg2;
++      arg1=TYPE_ARG_TYPES(type1);
++      arg2=TYPE_ARG_TYPES(type2);
++      for (; arg1 && arg2; arg1=TREE_CHAIN(arg1), arg2=TREE_CHAIN(arg2))
++	if (TREE_VALUE(arg1) && TREE_VALUE(arg2))
++	  {
++	    tree asm1, asm2;
++	    asm1=lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(arg1)));
++	    asm2=lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(arg2)));
++	    if (asm1 && asm2)
++	      {
++		if (TREE_INT_CST_LOW(TREE_VALUE(asm1))!=
++		    TREE_INT_CST_LOW(TREE_VALUE(asm2)))
++		  return 0; /* Two different registers specified. */
++	      }
++	    else
++	      if (asm1 || asm2)
++		return 0; /* "asm" used in only one type. */
++	  }
++    }
++  return 1;
++}
++
++/* end-TIGCC-local (regparms) */
+diff -Naur gcc-3.3.3.orig/gcc/config/m68k/m68k.h gcc-3.3.3.tigcc8/gcc/config/m68k/m68k.h
+--- gcc-3.3.3.orig/gcc/config/m68k/m68k.h	Tue Dec  3 19:45:30 2002
++++ gcc-3.3.3.tigcc8/gcc/config/m68k/m68k.h	Sun Aug  8 11:06:40 2004
+@@ -79,10 +79,8 @@
+ #define MASK_RTD	8
+ #define TARGET_RTD (target_flags & MASK_RTD)
+ 
+-/* Compile passing first two args in regs 0 and 1.
+-   This exists only to test compiler features that will
+-   be needed for RISC chips.  It is not usable
+-   and is not intended to be usable on this cpu.  */
++/* Compile using the first 'm68k_regparm' data, address and float
++   registers for arguments passing.  */
+ #define MASK_REGPARM	16
+ #define TARGET_REGPARM (target_flags & MASK_REGPARM)
+ 
+@@ -151,6 +149,39 @@
+ #define MASK_NO_STRICT_ALIGNMENT 16384
+ #define TARGET_STRICT_ALIGNMENT  (~target_flags & MASK_NO_STRICT_ALIGNMENT)
+ 
++/* Use the TIOS calling convention */
++#define MASK_TIOS	32768
++#define TARGET_TIOS	(target_flags & MASK_TIOS)
++
++/* Use the TIOS return convention for floats (not yet supported) */
++#define MASK_DIRECTFLOAT	65536
++#define TARGET_DIRECTFLOAT	(target_flags & MASK_DIRECTFLOAT)
++
++/* Access everything in relation to a specific register */
++#define MASK_REG_RELATIVE	131072
++#define TARGET_REG_RELATIVE	(target_flags & MASK_REG_RELATIVE)
++
++/* Use absolute line numbers in COFF debugging format */
++#define MASK_COFFABSLINES	524288
++#define TARGET_COFFABSLINES	(target_flags & MASK_COFFABSLINES)
++
++/* Merge .text and .data sections (to .text) */
++#define MASK_MERGE_SECTIONS	2097152
++#define TARGET_MERGE_SECTIONS	(target_flags & MASK_MERGE_SECTIONS)
++
++/* Merge sections to .data rather than to .text (ignored if MASK_MERGE_SECTIONS
++   is not set) */
++#define MASK_MERGE_TO_DATA	4194304
++#define TARGET_MERGE_TO_DATA	(target_flags & MASK_MERGE_TO_DATA)
++
++/* When not merging sections, put read-only data into .text rather than .data */
++#define MASK_RODATA_TO_TEXT	8388608
++#define TARGET_RODATA_TO_TEXT	(target_flags & MASK_RODATA_TO_TEXT)
++
++/* Never output any common or lcomm symbols, neither with nor without _nostub */
++#define MASK_NO_BSS	16777216
++#define TARGET_NO_BSS	(target_flags & MASK_NO_BSS)
++
+ /* Macro to define tables used to set the flags.
+    This is a list in braces of pairs in braces,
+    each pair being { "NAME", VALUE }
+@@ -180,8 +211,16 @@
+       N_("Use normal calling convention") },				\
+     { "short", MASK_SHORT,						\
+       N_("Consider type `int' to be 16 bits wide") },			\
++    { "nolong", MASK_SHORT,						\
++      N_("Consider type `int' to be 16 bits wide") },			\
++    { "no-long", MASK_SHORT,						\
++      N_("Consider type `int' to be 16 bits wide") },			\
++    { "long", - MASK_SHORT,						\
++      N_("Consider type `int' to be 32 bits wide") },			\
+     { "noshort", - MASK_SHORT,						\
+       N_("Consider type `int' to be 32 bits wide") },			\
++    { "no-short", - MASK_SHORT,						\
++      N_("Consider type `int' to be 32 bits wide") },			\
+     { "fpa", -(MASK_SKY|MASK_68040_ONLY|MASK_68881),			\
+       N_("Generate code for a Sun FPA") },				\
+     { "fpa", MASK_FPA, "" },						\
+@@ -237,14 +276,58 @@
+     { "cpu32", MASK_68020, "" },					\
+     { "align-int", MASK_ALIGN_INT, 					\
+       N_("Align variables on a 32-bit boundary") },			\
++    { "noalign-int", -MASK_ALIGN_INT, 					\
++      N_("Align variables on a 16-bit boundary") },			\
+     { "no-align-int", -MASK_ALIGN_INT, 					\
+       N_("Align variables on a 16-bit boundary") },			\
+     { "pcrel", MASK_PCREL,						\
+       N_("Generate pc-relative code") },				\
++    { "nopcrel", - MASK_PCREL,						\
++      N_("Generate absolute code") },					\
++    { "no-pcrel", - MASK_PCREL,						\
++      N_("Generate absolute code") },					\
+     { "strict-align", -MASK_NO_STRICT_ALIGNMENT,			\
+       N_("Do not use unaligned memory references") },			\
+     { "no-strict-align", MASK_NO_STRICT_ALIGNMENT,			\
+       N_("Use unaligned memory references") },				\
++    { "tios", MASK_TIOS,						\
++      N_("Enable TIOS interoperability") },				\
++    { "notios", - MASK_TIOS,						\
++      N_("Disable TIOS interoperability") },				\
++    { "no-tios", - MASK_TIOS,						\
++      N_("Disable TIOS interoperability") },				\
++    { "regparm", MASK_REGPARM,						\
++      N_("Allow passing by registers") },				\
++    { "noregparm", - MASK_REGPARM,					\
++      N_("Disallow passing by registers") },				\
++    { "no-regparm", - MASK_REGPARM,					\
++      N_("Disallow passing by registers") },				\
++    { "merge-sections", MASK_MERGE_SECTIONS,						\
++      N_("Merge the .text and .data sections") },				\
++    { "nomerge-sections", - MASK_MERGE_SECTIONS,					\
++      N_("Do not merge the .text and .data sections") },				\
++    { "no-merge-sections", - MASK_MERGE_SECTIONS,					\
++      N_("Do not merge the .text and .data sections") },				\
++    { "merge-to-data", MASK_MERGE_TO_DATA,						\
++      N_("When merging sections, merge to .data rather than to .text") },				\
++    { "nomerge-to-data", - MASK_MERGE_TO_DATA,					\
++      N_("When merging sections, merge to .text rather than to .data") },				\
++    { "no-merge-to-data", - MASK_MERGE_TO_DATA,					\
++      N_("When merging sections, merge to .text rather than to .data") },				\
++    { "rodata-to-text", MASK_RODATA_TO_TEXT,						\
++      N_("When not merging sections, put read-only data into .text rather than .data") },				\
++    { "norodata-to-text", - MASK_RODATA_TO_TEXT,					\
++      N_("When not merging sections, put read-only data into .data rather than .text") },				\
++    { "no-rodata-to-text", - MASK_RODATA_TO_TEXT,					\
++      N_("When not merging sections, put read-only data into .data rather than .text") },				\
++    { "bss", - MASK_NO_BSS,						\
++      N_("Output common/lcomm (BSS) symbols for uninitialized data") },				\
++    { "nobss", MASK_NO_BSS,					\
++      N_("Don't use common/lcomm (BSS) symbols for uninitialized data, zero-initialize it") },				\
++    { "no-bss", MASK_NO_BSS,					\
++      N_("Don't use common/lcomm (BSS) symbols for uninitialized data, zero-initialize it") },				\
++    { "coff-abslines", MASK_COFFABSLINES,				\
++      N_("Use absolute line numbers for COFF debugging") },		\
+     SUBTARGET_SWITCHES							\
+     { "", TARGET_DEFAULT, "" }}
+ /* TARGET_DEFAULT is defined in sun*.h and isi.h, etc.  */
+@@ -265,6 +348,8 @@
+     N_("Jump targets are aligned to this power of 2") },		\
+   { "align-functions=",	&m68k_align_funcs_string,			\
+     N_("Function starts are aligned to this power of 2") },		\
++  { "regparm=",		&m68k_regparm_string,				\
++    N_("Number of register parameters of each register type") },	\
+   SUBTARGET_OPTIONS							\
+ }
+ 
+@@ -284,6 +369,8 @@
+ #define SUBTARGET_OPTIONS
+ #define SUBTARGET_OVERRIDE_OPTIONS
+ 
++extern char TARGET_RELATION_REG[];
++
+ /* target machine storage layout */
+ 
+ /* Define for XFmode extended real floating point support.  */
+@@ -316,7 +403,7 @@
+ #define UNITS_PER_WORD 4
+ 
+ /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
+-#define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32)
++#define PARM_BOUNDARY 16
+ 
+ /* Boundary (in *bits*) on which stack pointer should be aligned.  */
+ #define STACK_BOUNDARY 16
+@@ -817,6 +904,9 @@
+    `Q' means address register indirect addressing mode.
+    `S' is for operands that satisfy 'm' when -mpcrel is in effect.
+    `T' is for operands that satisfy 's' when -mpcrel is not in effect.  */
++/* (TIGCC 20040808) Under -freg-relative-an, the same restrictions on 's'/'T' as
++                    for -mpcrel apply. We can't use immediates as labels if
++                    we need to output reg-relative code. -- Kevin Kofler  */
+ 
+ #define EXTRA_CONSTRAINT(OP,CODE)			\
+   (((CODE) == 'S')					\
+@@ -827,7 +917,7 @@
+ 	  || GET_CODE (XEXP (OP, 0)) == CONST))		\
+    : 							\
+   (((CODE) == 'T')					\
+-   ? ( !TARGET_PCREL 					\
++   ? ( (!TARGET_PCREL && !TARGET_REG_RELATIVE) 					\
+       && (GET_CODE (OP) == SYMBOL_REF			\
+ 	  || GET_CODE (OP) == LABEL_REF			\
+ 	  || GET_CODE (OP) == CONST))			\
+@@ -998,10 +1088,17 @@
+ 
+ #define PCC_STATIC_STRUCT_RETURN
+ 
+-/* 1 if N is a possible register number for function argument passing.
+-   On the 68000, no registers are used in this way.  */
++/* Define this if explicit register specification for parameters
++   is supported.  */
++
++#define EXPLICIT_REGPARM
+ 
+-#define FUNCTION_ARG_REGNO_P(N) 0
++/* 1 if N is a possible register number for function argument passing.  */
++
++#define FUNCTION_ARG_REGNO_P(N)			\
++  (((N) >= 0 && (N) < M68K_MAX_REGPARM)		\
++   || ((N) >= 8 && (N) < 8 + M68K_MAX_REGPARM)	\
++   || (TARGET_68881 && (N) >= 16 && (N) < 16 + M68K_MAX_REGPARM))
+ 
+ /* Define a data type for recording info about an argument list
+    during the scan of that argument list.  This data type should
+@@ -1009,28 +1106,54 @@
+    and about the args processed so far, enough to enable macros
+    such as FUNCTION_ARG to determine where the next arg should go.
+ 
+-   On the m68k, this is a single integer, which is a number of bytes
+-   of arguments scanned so far.  */
++   On the m68k, this is a structure:
++   num_of_regs: number of data, address and float registers to use for
++     arguments passing (if it's 2, than pass arguments in d0, d1, a0, a1,
++     fp0 and fp1). 0 - pass everything on stack. vararg calls are
++     always passed entirely on stack.
++   regs_already_used: bitmask of the already used registers.
++   last_arg_reg: register number of the most recently passed argument.
++     -1 if passed on stack.
++   last_arg_len: number of registers used by the most recently passed
++     argument.
++   formal_type: formal type of the current argument.
++*/
++
++struct m68k_args
++{
++  int num_of_regs;
++  long regs_already_used;
++  int last_arg_reg;
++  int last_arg_len;
++  void *formal_type;
++};
++
++#define CUMULATIVE_ARGS struct m68k_args
++
++/* Max. number of data, address and float registers to be used for passing
++   integer, pointer and float arguments when TARGET_REGPARM.
++   It's 7, so d0-d6, a0-a6 and fp0-fp6 can be used.  */
++
++#define M68K_MAX_REGPARM 6  /* was 4 in the original patch */
+ 
+-#define CUMULATIVE_ARGS int
++/* The default number of data, address and float registers to use when
++   user specified '-mregparm' switch, not '-mregparm=<value>' option.  */
++
++#define M68K_DEFAULT_REGPARM 2  /* was 2 in the orginial patch */
+ 
+ /* Initialize a variable CUM of type CUMULATIVE_ARGS
+    for a call to a function whose data type is FNTYPE.
+-   For a library call, FNTYPE is 0.
+-
+-   On the m68k, the offset starts at 0.  */
++   For a library call, FNTYPE is 0.  */
+ 
+ #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT)	\
+- ((CUM) = 0)
++  (amigaos_init_cumulative_args (&(CUM), (FNTYPE)))
+ 
+ /* Update the data in CUM to advance over an argument
+    of mode MODE and data type TYPE.
+    (TYPE is null for libcalls where that information may not be available.)  */
+ 
+ #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
+- ((CUM) += ((MODE) != BLKmode			\
+-	    ? (GET_MODE_SIZE (MODE) + 3) & ~3	\
+-	    : (int_size_in_bytes (TYPE) + 3) & ~3))
++  (amigaos_function_arg_advance (&(CUM)))
+ 
+ /* Define where to put the arguments to a function.
+    Value is zero to push the argument on the stack,
+@@ -1045,24 +1168,14 @@
+    NAMED is nonzero if this argument is a named parameter
+     (otherwise it is an extra parameter matching an ellipsis).  */
+ 
+-/* On the 68000 all args are pushed, except if -mregparm is specified
+-   then the first two words of arguments are passed in d0, d1.
+-   *NOTE* -mregparm does not work.
+-   It exists only to test register calling conventions.  */
+-
+ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+-((TARGET_REGPARM && (CUM) < 8) ? gen_rtx_REG ((MODE), (CUM) / 4) : 0)
++  ((struct rtx_def *)amigaos_function_arg (&(CUM), (MODE), (TYPE)))
+ 
+ /* For an arg passed partly in registers and partly in memory,
+    this is the number of registers used.
+    For args passed entirely in registers or entirely in memory, zero.  */
+ 
+-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+-((TARGET_REGPARM && (CUM) < 8					\
+-  && 8 < ((CUM) + ((MODE) == BLKmode				\
+-		      ? int_size_in_bytes (TYPE)		\
+-		      : GET_MODE_SIZE (MODE))))  		\
+- ? 2 - (CUM) / 4 : 0)
++#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0)
+ 
+ /* Output assembler code to FILE to increment profiler label # LABELNO
+    for profiling a function entry.  */
+@@ -1256,8 +1369,11 @@
+ 
+ /* Nonzero if the constant value X is a legitimate general operand.
+    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
++/* (TIGCC 20040808) If reg-relative, we need to reject "constants" of the #label
++                    or #label+const form. -- Kevin Kofler  */
+ 
+-#define LEGITIMATE_CONSTANT_P(X) 1
++#define LEGITIMATE_CONSTANT_P(X) (!TARGET_REG_RELATIVE \
++                                  || !pcrel_address (X, VOIDmode))
+ 
+ /* Nonzero if the constant value X is a legitimate general operand
+    when generating PIC code.  It is given that flag_pic is on and 
+@@ -1554,8 +1670,13 @@
+    taking away a little more because sometimes move insns are needed.  */
+ /* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms.  */
+ #define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : 13)
+-#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : 5)
+-#define DIVW_COST (TARGET_68020 ? 27 : 12)
++/* (TIGCC 20030705) Decrease multiplication/division cost under -Os, so that
++                    muls/divs/divu gets preferred over large expansions of
++                    shifts & adds.
++                    -- Kevin Kofler */
++#define MULW_COST (optimize_size ? 3 : (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : 5))
++#define DIVW_COST (optimize_size ? 3 : (TARGET_68020 ? 27 : 12))
++#define UDIVW_COST (optimize_size ? 6 : (TARGET_68020 ? 27 : 12))
+ 
+ #define RTX_COSTS(X,CODE,OUTER_CODE)				\
+   case PLUS:							\
+@@ -1579,11 +1700,12 @@
+       {									\
+ 	if (GET_CODE (XEXP (X, 1)) == CONST_INT)			\
+ 	  {								\
++/* (TIGCC 20030705) shifts costs under -Os are instruction counts, not cycle counts -- Kevin Kofler */ \
+ 	    if (INTVAL (XEXP (X, 1)) < 16)				\
+-	      return COSTS_N_INSNS (2) + INTVAL (XEXP (X, 1)) / 2;	\
++	      return COSTS_N_INSNS (2) + INTVAL (XEXP (X, 1)) / (optimize_size ? 9 : 2);	\
+ 	    else							\
+ 	      /* We're using clrw + swap for these cases.  */		\
+-	      return COSTS_N_INSNS (4) + (INTVAL (XEXP (X, 1)) - 16) / 2; \
++	      return COSTS_N_INSNS (4) + (INTVAL (XEXP (X, 1)) - 16) / (optimize_size ? 9 : 2); \
+ 	  }								\
+ 	return COSTS_N_INSNS (10); /* worst case */			\
+       }									\
+@@ -1605,12 +1727,17 @@
+       return COSTS_N_INSNS (MULW_COST);				\
+     else							\
+       return COSTS_N_INSNS (MULL_COST);				\
++/* (TIGCC 20030705) distinguish signed vs. unsigned division */ \
++/* - ext is cheaper than the unsigned equivalent -- Kevin Kofler */ \
+   case DIV:							\
+-  case UDIV:							\
+   case MOD:							\
+-  case UMOD:							\
+     if (GET_MODE (X) == QImode || GET_MODE (X) == HImode)	\
+       return COSTS_N_INSNS (DIVW_COST); /* div.w */		\
++    return COSTS_N_INSNS (43);	 /* div.l */ \
++  case UDIV:							\
++  case UMOD:							\
++    if (GET_MODE (X) == QImode || GET_MODE (X) == HImode)	\
++      return COSTS_N_INSNS (UDIVW_COST); /* div.w */		\
+     return COSTS_N_INSNS (43);	 /* div.l */
+ 
+ /* Tell final.c how to eliminate redundant test instructions.  */
+@@ -1812,18 +1939,22 @@
+ /* This says how to output an assembler line
+    to define a global common symbol.  */
+ 
++#ifndef ASM_OUTPUT_COMMON
+ #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
+ ( fputs (".comm ", (FILE)),			\
+   assemble_name ((FILE), (NAME)),		\
+   fprintf ((FILE), ",%u\n", (ROUNDED)))
++#endif
+ 
+ /* This says how to output an assembler line
+    to define a local common symbol.  */
+ 
++#ifndef ASM_OUTPUT_LOCAL
+ #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
+ ( fputs (".lcomm ", (FILE)),			\
+   assemble_name ((FILE), (NAME)),		\
+   fprintf ((FILE), ",%u\n", (ROUNDED)))
++#endif
+ 
+ /* Store in OUTPUT a string (made with alloca) containing
+    an assembler-name for a local static variable named NAME.
+@@ -1935,13 +2066,36 @@
+ 
+ #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+ 
++/* Attributes support.  */
++
++#if 0  /* This has moved to TARGET_INITIALIZER, initialized in m68k.c.  */
++
++/* A C expression whose value is nonzero if IDENTIFIER with arguments
++   ARGS is a valid machine specific attribute for TYPE.  The attributes
++   in ATTRIBUTES have previously been assigned to TYPE.  */
++
++#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \
++  (valid_m68k_type_attribute ((TYPE), (ATTRIBUTES), (IDENTIFIER), (ARGS)))
++
++/* A C expression whose value is zero if the attributes on TYPE1 and
++   TYPE2 are incompatible, one if they are compatible, and two if they
++   are nearly compatible (which causes a warning to be generated).  */
++
++#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
++  (comp_amigaos_type_attributes ((TYPE1), (TYPE2)))
++
++#endif
++
++
+ /* Variables in m68k.c */
+ extern const char *m68k_align_loops_string;
+ extern const char *m68k_align_jumps_string;
+ extern const char *m68k_align_funcs_string;
++extern const char *m68k_regparm_string;
+ extern int m68k_align_loops;
+ extern int m68k_align_jumps;
+ extern int m68k_align_funcs;
++extern int m68k_regparm;
+ extern int m68k_last_compare_had_fp_operands;
+ 
+ 
+@@ -1958,7 +2112,11 @@
+   {"const_sint32_operand", {CONST_INT}},				\
+   {"valid_dbcc_comparison_p", {EQ, NE, GTU, LTU, GEU, LEU,		\
+ 			       GT, LT, GE, LE}},			\
+-  {"extend_operator", {SIGN_EXTEND, ZERO_EXTEND}},
++  {"extend_operator", {SIGN_EXTEND, ZERO_EXTEND}}, \
++  /* (TIGCC 20040222) used in the indirect_jump pattern -- Kevin Kofler */\
++  {"extended_address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
++                                LABEL_REF, SUBREG, REG, MEM, ADDRESSOF, \
++                                PLUS, MINUS, MULT}},
+ 
+ /*
+ Local variables:
+diff -Naur gcc-3.3.3.orig/gcc/config/m68k/m68k.md gcc-3.3.3.tigcc8/gcc/config/m68k/m68k.md
+--- gcc-3.3.3.orig/gcc/config/m68k/m68k.md	Thu Jun 12 23:56:58 2003
++++ gcc-3.3.3.tigcc8/gcc/config/m68k/m68k.md	Sun Aug  8 10:25:16 2004
+@@ -522,6 +522,8 @@
+   "!TARGET_5200"
+   "*
+ {
++/* (TIGCC 20040222) This used %d0 and %d1 to force absolute addressing, which
++                    doesn't make sense and breaks -mpcrel. -- Kevin Kofler */
+   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ #ifdef SGS_CMP_ORDER
+     return \"cmpm%.l %0,%1\";
+@@ -532,9 +534,9 @@
+       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+     { cc_status.flags |= CC_REVERSED;
+ #ifdef SGS_CMP_ORDER
+-      return \"cmp%.l %d1,%d0\";
++      return \"cmp%.l %1,%0\";
+ #else
+-      return \"cmp%.l %d0,%d1\";
++      return \"cmp%.l %0,%1\";
+ #endif
+     }
+   if (ADDRESS_REG_P (operands[0])
+@@ -549,9 +551,9 @@
+ #endif
+     }
+ #ifdef SGS_CMP_ORDER
+-  return \"cmp%.l %d0,%d1\";
++  return \"cmp%.l %0,%1\";
+ #else
+-  return \"cmp%.l %d1,%d0\";
++  return \"cmp%.l %1,%0\";
+ #endif
+ }")
+ 
+@@ -578,20 +580,28 @@
+ #endif
+ }")
+ 
++;; (TIGCC 20040808) Don't allow non-source operands as the destination in the
++;;                  compare. We need to use nonimmediate_operand, not
++;;                  nonimmediate_src_operand. Otherwise, -mpcrel outputs invalid
++;;                  assembly code. The SImode patterns already got this right.
++;; -- Kevin Kofler
++
+ (define_expand "cmphi"
+   [(set (cc0)
+-        (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
++        (compare (match_operand:HI 0 "nonimmediate_operand" "")
+                  (match_operand:HI 1 "general_src_operand" "")))]
+   "!TARGET_5200"
+   "m68k_last_compare_had_fp_operands = 0;")
+ 
+ (define_insn ""
+   [(set (cc0)
+-        (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>")
++        (compare (match_operand:HI 0 "nonimmediate_operand" "rnmS,d,n,mS,>")
+                  (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))]
+   "!TARGET_5200"
+   "*
+ {
++/* (TIGCC 20040222) This used %d0 and %d1 to force absolute addressing, which
++                    doesn't make sense and breaks -mpcrel. -- Kevin Kofler */
+   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ #ifdef SGS_CMP_ORDER
+     return \"cmpm%.w %0,%1\";
+@@ -602,32 +612,34 @@
+       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+     { cc_status.flags |= CC_REVERSED;
+ #ifdef SGS_CMP_ORDER
+-      return \"cmp%.w %d1,%d0\";
++      return \"cmp%.w %1,%0\";
+ #else
+-      return \"cmp%.w %d0,%d1\";
++      return \"cmp%.w %0,%1\";
+ #endif
+     }
+ #ifdef SGS_CMP_ORDER
+-  return \"cmp%.w %d0,%d1\";
++  return \"cmp%.w %0,%1\";
+ #else
+-  return \"cmp%.w %d1,%d0\";
++  return \"cmp%.w %1,%0\";
+ #endif
+ }")
+ 
+ (define_expand "cmpqi"
+   [(set (cc0)
+-        (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
++        (compare (match_operand:QI 0 "nonimmediate_operand" "")
+                  (match_operand:QI 1 "general_src_operand" "")))]
+   "!TARGET_5200"
+   "m68k_last_compare_had_fp_operands = 0;")
+ 
+ (define_insn ""
+   [(set (cc0)
+-        (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>")
++        (compare (match_operand:QI 0 "nonimmediate_operand" "dn,dmS,>")
+                  (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))]
+   "!TARGET_5200"
+   "*
+ {
++/* (TIGCC 20040222) This used %d0 and %d1 to force absolute addressing, which
++                    doesn't make sense and breaks -mpcrel. -- Kevin Kofler */
+   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ #ifdef SGS_CMP_ORDER
+     return \"cmpm%.b %0,%1\";
+@@ -638,15 +650,15 @@
+       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+     { cc_status.flags |= CC_REVERSED;
+ #ifdef SGS_CMP_ORDER
+-      return \"cmp%.b %d1,%d0\";
++      return \"cmp%.b %1,%0\";
+ #else
+-      return \"cmp%.b %d0,%d1\";
++      return \"cmp%.b %0,%1\";
+ #endif
+     }
+-#ifdef SGS_CMP_ORDER
+-  return \"cmp%.b %d0,%d1\";
++#ifdef SGS_CMP_ORDER  
++  return \"cmp%.b %0,%1\";
+ #else
+-  return \"cmp%.b %d1,%d0\";
++  return \"cmp%.b %1,%0\";
+ #endif
+ }")
+ 
+@@ -998,10 +1010,11 @@
+ 
+ ;; Special case of fullword move, where we need to get a non-GOT PIC
+ ;; reference into an address register.
++;; (TIGCC 20040808) This is also needed for -freg-relative-an. -- Kevin Kofler
+ (define_insn ""
+   [(set (match_operand:SI 0 "nonimmediate_operand" "=a<")
+         (match_operand:SI 1 "pcrel_address" ""))]
+-  "TARGET_PCREL"
++  "TARGET_PCREL || TARGET_REG_RELATIVE"
+   "*
+ {
+   if (push_operand (operands[0], SImode))
+@@ -1251,6 +1264,31 @@
+   "TARGET_5200"
+   "* return output_move_double (operands);")
+ 
++(define_expand "movbf"
++  ;; SMAP BCD
++  [(set (match_operand:BF 0 "nonimmediate_operand" "")
++	(match_operand:BF 1 "general_operand" ""))]
++  ""
++  "
++{
++  if (CONSTANT_P (operands[1]))
++    {
++      operands[1] = force_const_mem (BFmode, operands[1]);
++      if (! memory_address_p (BFmode, XEXP (operands[1], 0))
++	  && ! reload_in_progress)
++	operands[1] = adjust_address (operands[1], BFmode, 0);
++    }
++  if (flag_pic && TARGET_PCREL && ! reload_in_progress)
++    {
++      /* Don't allow writes to memory except via a register;
++	 the m68k doesn't consider PC-relative addresses to be writable.  */
++      if (GET_CODE (operands[0]) == MEM
++	  && symbolic_operand (XEXP (operands[0], 0), SImode))
++	operands[0] = gen_rtx (MEM, BFmode,
++			       force_reg (SImode, XEXP (operands[0], 0)));
++    }
++}")
++ 
+ (define_expand "movxf"
+   [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ 	(match_operand:XF 1 "general_operand" ""))]
+@@ -1317,6 +1355,48 @@
+ ")
+ 
+ (define_insn ""
++  ;; SMAP BCD
++  [(set (match_operand:BF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
++	(match_operand:BF 1 "nonimmediate_operand" "rf,m,rof<>"))]
++  "! TARGET_68881 && ! TARGET_5200"
++  "*
++{
++  if (FP_REG_P (operands[0]))
++    {
++      if (FP_REG_P (operands[1]))
++	return \"fmove%.x %1,%0\";
++      if (REG_P (operands[1]))
++	{
++	  rtx xoperands[2];
++	  xoperands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 2);
++	  output_asm_insn (\"move%.w %1,%-\", xoperands);
++	  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
++	  output_asm_insn (\"move%.l %1,%-\", xoperands);
++	  output_asm_insn (\"move%.l %1,%-\", operands);
++	  return \"fmove%.x %+,%0\";
++	}
++      if (GET_CODE (operands[1]) == CONST_DOUBLE)
++        return \"fmove%.x %1,%0\";
++      return \"fmove%.x %f1,%0\";
++    }
++  if (FP_REG_P (operands[1]))
++    {
++      if (REG_P (operands[0]))
++        {
++          output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands);
++          operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
++          output_asm_insn (\"move%.l %+,%0\", operands);
++          operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
++          return \"move%.w %+,%0\";
++        }
++      else
++        return \"fmove%.x %f1,%0\";
++    }
++  return output_move_double (operands);
++}
++")
++
++(define_insn ""
+   [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
+ 	(match_operand:XF 1 "nonimmediate_operand" "rf,m,rof<>"))]
+   "! TARGET_68881 && ! TARGET_5200"
+@@ -4844,7 +4924,11 @@
+       output_asm_insn (INTVAL (operands[2]) <= 8 ? \"asr%.l %2,%0\" :
+ 			\"moveq %2,%1\;asr%.l %1,%0\", operands);
+       output_asm_insn (\"mov%.l %0,%1\;smi %0\", operands);
+-      return INTVAL (operands[2]) >= 15 ? \"ext%.w %d0\" :
++/* (TIGCC 20040222) The %d0 here was a typo or thinko. It means 'force absolute
++                    addressing' in this context, not 'data register'. This
++                    doesn't make sense in a context where only data registers
++                    are allowed, so I removed it. -- Kevin Kofler */
++      return INTVAL (operands[2]) >= 15 ? \"ext%.w %0\" :
+ 	     TARGET_68020 ? \"extb%.l %0\" : \"ext%.w %0\;ext%.l %0\";
+     }
+ } ")
+@@ -7318,7 +7402,7 @@
+   if (GET_CODE (operands[0]) == MEM
+       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+     {
+-      if (TARGET_PCREL) return \"bsr.l %o0\";
++      if (TARGET_PCREL) return \"jbsr %o0\"; /* (TIGCC 20040222) */
+ #ifdef MOTOROLA
+ #ifdef HPUX_ASM
+       return \"bsr.l %0\";
+@@ -7388,7 +7472,7 @@
+   if (GET_CODE (operands[1]) == MEM
+       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+     {
+-      if (TARGET_PCREL) return \"bsr.l %o1\";
++      if (TARGET_PCREL) return \"jbsr %o1\"; /* (TIGCC 20040222) */
+ #ifdef MOTOROLA
+ #ifdef HPUX_ASM
+       return \"bsr.l %1\";
+@@ -7475,10 +7559,13 @@
+   return \"rtd %0\";
+ }")
+ 
++;; (TIGCC 20040222) Use jra instead of jmp here. Also don't add (%pc) under
++;;                  -mpcrel. Moreover, we need to handle extended address
++;;                  operands here. -- Kevin Kofler
+ (define_insn "indirect_jump"
+-  [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
++  [(set (pc) (match_operand:SI 0 "extended_address_operand" "p"))]
+   ""
+-  "jmp %a0")
++  "jra %A0")
+ 
+ ;; This should not be used unless the add/sub insns can't be.
+ 
+diff -Naur gcc-3.3.3.orig/gcc/config/smapbcd.h gcc-3.3.3.tigcc8/gcc/config/smapbcd.h
+--- gcc-3.3.3.orig/gcc/config/smapbcd.h	Thu Jan  1 01:00:00 1970
++++ gcc-3.3.3.tigcc8/gcc/config/smapbcd.h	Thu Feb 19 21:20:02 2004
+@@ -0,0 +1,507 @@
++/* Definitions for SMAP II BCD support in the GNU C Compiler.
++   These macros implement software BCD floating point support;
++   primary use will be TIGCC.
++   Copyright (C) 1994 Free Software Foundation, Inc.
++   Copyright (C) 2000 Sebastian Reichelt
++
++This file is part of TIGCC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING. If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA. */
++
++#include <math.h> /* finite() */
++#undef NAN
++
++#undef TARGET_FLOAT_FORMAT
++#define	TARGET_FLOAT_FORMAT SMAP_BCD_FLOAT_FORMAT
++
++#ifndef __SMAP_BCD_FLOAT
++#define __SMAP_BCD_FLOAT
++
++typedef struct real_value smap_bcd_float;
++
++#endif
++
++#undef REAL_VALUE_TYPE
++#define REAL_VALUE_TYPE smap_bcd_float
++
++#undef FLOAT_TYPE_SIZE
++#undef DOUBLE_TYPE_SIZE
++#undef LONG_DOUBLE_TYPE_SIZE
++
++/* We have to define a special mode for this; one that handles 10 byte
++   floats. There have to be a lot of changes to other files; due to the
++   fact that they are so countless, it would be too hard to make them
++   compatible with a general-purpose GCC. */
++#define FLOAT_TYPE_SIZE 80
++#define DOUBLE_TYPE_SIZE 80
++#define LONG_DOUBLE_TYPE_SIZE 80
++
++#ifndef REAL_IS_NOT_DOUBLE
++#define REAL_IS_NOT_DOUBLE
++#endif
++
++#define ZERO (__extension__(smap_bcd_float){0x4000,0})
++#define UNSIGNED_ZERO (__extension__(smap_bcd_float){0x4000,0})
++#define POSITIVE_ZERO (__extension__(smap_bcd_float){0,0})
++#define NEGATIVE_ZERO (__extension__(smap_bcd_float){0x8000,0})
++
++#define UNSIGNED_INF (__extension__(smap_bcd_float){0x7FFF,0xAA00CC0000000000})
++#define POSITIVE_INF (__extension__(smap_bcd_float){0x7FFF,0xAA00BB0000000000})
++#define NEGATIVE_INF (__extension__(smap_bcd_float){0xFFFF,0xAA00BB0000000000})
++
++#define NAN (__extension__(smap_bcd_float){0x7FFF,0xAA00000000000000})
++
++#ifndef REAL_INFINITY
++#define REAL_INFINITY
++#endif
++
++#undef REAL_VALUE_ISNAN
++#define REAL_VALUE_ISNAN(x) \
++	(REAL_VALUES_IDENTICAL (x, NAN))
++
++#undef REAL_VALUE_ISINF
++#define REAL_VALUE_ISINF(x) \
++	((REAL_VALUES_IDENTICAL (x, POSITIVE_INF)) \
++	|| (REAL_VALUES_IDENTICAL (x, NEGATIVE_INF)) \
++	|| (REAL_VALUES_IDENTICAL (x, UNSIGNED_INF)))
++
++#define REAL_VALUE_ISNANUINF(x) \
++	((REAL_VALUE_ISNAN (x)) \
++	|| (REAL_VALUES_IDENTICAL (x, UNSIGNED_INF)))
++
++#define REAL_VALUE_ISFINITE(x) \
++	(!(REAL_VALUE_ISNAN (x)) \
++	&& !(REAL_VALUE_ISINF (x)))
++
++#define REAL_VALUE_ISZERO(x) \
++	(!((x).mantissa))
++
++#undef REAL_VALUE_MINUS_ZERO
++#define REAL_VALUE_MINUS_ZERO(x) \
++	(REAL_VALUES_IDENTICAL (x, NEGATIVE_ZERO))
++
++#define REAL_VALUE_ISPOSITIVE(x) \
++	(!(REAL_VALUE_ISNANUINF (x)) \
++	&& ((x).exponent < 0x8000) \
++	&& !(REAL_VALUE_ISZERO (x)))
++
++#define REAL_VALUE_ISNEGATIVE(x) \
++	(!(REAL_VALUE_ISNANUINF (x)) \
++	&& ((x).exponent >= 0x8000) \
++	&& !(REAL_VALUE_ISZERO (x)))
++
++#undef REAL_VALUE_POSITIVE
++#define REAL_VALUE_POSITIVE(x) \
++	(REAL_VALUE_ISPOSITIVE (x))
++
++#undef REAL_VALUE_NEGATIVE
++#define REAL_VALUE_NEGATIVE(x) \
++	(REAL_VALUE_ISNEGATIVE (x))
++
++#undef REAL_VALUES_IDENTICAL
++#define REAL_VALUES_IDENTICAL(x, y) \
++	((x).exponent == (y).exponent && (x).mantissa == (y).mantissa)
++
++#undef REAL_VALUES_EQUAL
++#define REAL_VALUES_EQUAL(x,y) \
++	(((REAL_VALUES_IDENTICAL (x, y)) \
++	&& REAL_VALUE_ISFINITE (x) \
++	&& REAL_VALUE_ISFINITE (y)) \
++	|| (REAL_VALUE_ISZERO (x) \
++	&& REAL_VALUE_ISZERO (y)))
++
++#undef REAL_VALUES_LESS
++#define REAL_VALUES_LESS(x,y) \
++__extension__ ({ \
++	register int result = 0; \
++	if (REAL_VALUE_ISNANUINF (x) \
++		|| REAL_VALUE_ISNANUINF (y) \
++		|| REAL_VALUES_EQUAL (x, y) \
++		|| (REAL_VALUE_ISPOSITIVE (x) && !(REAL_VALUE_ISPOSITIVE (y))) \
++		|| (!(REAL_VALUE_ISNEGATIVE (x)) && REAL_VALUE_ISNEGATIVE (y))) \
++		result = 0; \
++	else if ((REAL_VALUE_ISNEGATIVE (x) && !(REAL_VALUE_ISNEGATIVE (y))) \
++		|| (!(REAL_VALUE_ISPOSITIVE (x)) && REAL_VALUE_ISPOSITIVE (y))) \
++		result = 1; \
++	else \
++	{ \
++		if ((x).exponent == (y).exponent) \
++		{ \
++			if (REAL_VALUE_ISNEGATIVE (x)) \
++				result = ((x).mantissa > (y).mantissa); \
++			else \
++				result = ((x).mantissa < (y).mantissa); \
++		} \
++		else \
++		{ \
++			if (REAL_VALUE_ISNEGATIVE (x)) \
++				result = ((x).exponent > (y).exponent); \
++			else \
++				result = ((x).exponent < (y).exponent); \
++		} \
++	} \
++	result; \
++})
++
++#undef REAL_VALUE_LDEXP
++#define REAL_VALUE_LDEXP(x,tempscale) \
++__extension__ ({ \
++	REAL_VALUE_TYPE __tempx = x; \
++	int scale; \
++	unsigned long long pmul; \
++	signed short carry, help; \
++	if (REAL_VALUE_ISFINITE (__tempx)) \
++	{ \
++		if (tempscale > 0) \
++			for (scale = 0; scale < tempscale; scale++) \
++			{ \
++				if (__tempx.mantissa >= 0x5000000000000000) \
++				{ \
++					__tempx.mantissa /= 0x10; \
++					__tempx.exponent++; \
++				} \
++				carry = 0; \
++				for (pmul = 1; 1; pmul *= 0x10) \
++				{ \
++					help = (__tempx.mantissa / pmul) & 0xF; \
++					__tempx.mantissa -= ((unsigned long long) help) * pmul; \
++					help *= 2; \
++					help += carry; \
++					carry = help / 10; \
++					__tempx.mantissa += ((unsigned long long) (help % 10)) * pmul; \
++					if (pmul >= 0x1000000000000000) \
++						break; \
++				} \
++			} \
++		else if (tempscale < 0) \
++			for (scale = 0; scale > tempscale; scale--) \
++			{ \
++				carry = 0; \
++				for (pmul = 0x1000000000000000; pmul > 0; pmul /= 0x10) \
++				{ \
++					help = (__tempx.mantissa / pmul) & 0xF; \
++					__tempx.mantissa -= ((unsigned long long) help) * pmul; \
++					help += carry; \
++					__tempx.mantissa += ((unsigned long long) (help / 2)) * pmul; \
++					carry = (help % 2) * 10; \
++				} \
++				if (__tempx.mantissa < 0x1000000000000000) \
++				{ \
++					__tempx.mantissa *= 0x10; \
++					__tempx.mantissa += carry / 2; \
++					__tempx.exponent--; \
++				} \
++			} \
++	} \
++	__tempx; \
++})
++
++#undef REAL_VALUE_FIX
++#define REAL_VALUE_FIX(x) \
++	((REAL_VALUE_ISNEGATIVE (x)) \
++	? (-(REAL_VALUE_UNSIGNED_FIX (REAL_VALUE_NEGATE (x)))) \
++	: (REAL_VALUE_UNSIGNED_FIX (x)))
++
++#undef REAL_VALUE_UNSIGNED_FIX
++#define REAL_VALUE_UNSIGNED_FIX(x) \
++__extension__ ({ \
++	register unsigned int r = 0; \
++	signed char i; \
++	unsigned long long mpmul = 0x1000000000000000; \
++	if (((x.exponent & 0x7FFF) >= 0x4000) && ((x.exponent & 0x7FFF) < 0x4016)) \
++	{ \
++		for (i = 0; i <= (x.exponent & 0x7FFF) - 0x4000; i++) \
++			if (mpmul) \
++			{ \
++				r *= 10; \
++				r += (x.mantissa / mpmul) & 0xF; \
++				mpmul /= 0x10; \
++			} \
++	} \
++	r; \
++})
++
++#undef REAL_VALUE_RNDZINT
++#define REAL_VALUE_RNDZINT(x) \
++__extension__ ({ \
++	REAL_VALUE_TYPE r = ZERO; \
++	signed char i; \
++	unsigned long long mpmul = 0x1000000000000000; \
++	r.exponent = (x).exponent; \
++	if (((r.exponent & 0x7FFF) >= 0x4000) && ((r.exponent & 0x7FFF) < 0x4016)) \
++	{ \
++		for (i = 0; i <= (r.exponent & 0x7FFF) - 0x4000; i++) \
++			if (mpmul) \
++			{ \
++				r.mantissa += x.mantissa & (0xF * mpmul); \
++				mpmul /= 0x10; \
++			} \
++	} \
++	r; \
++})
++
++#undef REAL_VALUE_UNSIGNED_RNDZINT
++#define REAL_VALUE_UNSIGNED_RNDZINT(x) \
++	((REAL_VALUE_ISPOSITIVE (x)) \
++	? (REAL_VALUE_RNDZINT (x)) \
++	: (ZERO))
++
++#undef REAL_VALUE_ATOF
++#define REAL_VALUE_ATOF(string,mode) \
++	(strchr(string,'p') ? REAL_VALUE_HTOF(string,mode) \
++	                    : REAL_VALUE_DTOF(string,mode))
++
++#undef REAL_VALUE_DTOF
++#define REAL_VALUE_DTOF(string,mode) \
++__extension__ ({ \
++	REAL_VALUE_TYPE r; \
++	char *strpart = string; \
++	unsigned char state = 0; \
++	unsigned long long mpmul = 0x1000000000000000; \
++	signed short expshift = -1; \
++	unsigned short exp = 0; \
++	unsigned short expmul = 1; \
++	unsigned short expadd = 0x4000; \
++	r.mantissa = 0; \
++	while (strpart && *strpart) \
++	{ \
++		switch (state) \
++		{ \
++			case 0: \
++				if (*strpart == '.') \
++				{ \
++					state = 1; \
++					break; \
++				} \
++				else if (*strpart == '+') \
++					expadd = 0x4000; \
++				else if (*strpart == '-') \
++					expadd = 0xC000; \
++				else if (((*strpart) >= '0' && (*strpart) <= '9') && ((r.mantissa) || (*strpart != '0'))) \
++					expshift++; \
++				else if ((*strpart == 'i') || (*strpart == 'I')) \
++				{ \
++					if (expadd == 0xC000) \
++						r = NEGATIVE_INF; \
++					else \
++						r = POSITIVE_INF; \
++					expadd = 0x7FFF; \
++					strpart = 0; \
++				} \
++				else if ((*strpart == 'n') || (*strpart == 'N')) \
++				{ \
++					r = NAN; \
++					expadd = 0x7FFF; \
++					strpart = 0; \
++				} \
++			case 1: \
++				if ((*strpart == 'e') || (*strpart == 'E')) \
++					state = 2; \
++				else if ((*strpart) >= '0' && (*strpart) <= '9') \
++				{ \
++					r.mantissa |= (*strpart - '0') * mpmul; \
++					if (r.mantissa) \
++						mpmul /= 0x10; \
++					else if (state) \
++						expshift--; \
++				} \
++				break; \
++			case 2: \
++				if (*strpart == '+') \
++					expmul = 1; \
++				else if (*strpart == '-') \
++					expmul = -1; \
++				if ((*strpart) >= '0' && (*strpart) <= '9') \
++				{ \
++					exp *= 10; \
++					exp += (*strpart - '0'); \
++				} \
++				break; \
++		} \
++		if (strpart) \
++			((unsigned long) (strpart))++; \
++		else \
++			break; \
++	} \
++	if (!(r.mantissa)) \
++		r = ZERO; \
++	else if (expadd != 0x7FFF) \
++		r.exponent = exp * expmul + expadd + expshift; \
++	r; \
++})
++
++#undef REAL_VALUE_HTOF
++#define REAL_VALUE_HTOF(string,mode) \
++__extension__ ({ \
++	REAL_VALUE_TYPE res; \
++	char tempstr [100]; \
++	double r = 0.0; \
++	char *strpart = string; \
++	signed char state = -1; \
++	unsigned long rdiv = 1; \
++	unsigned int negative = 0; \
++	unsigned short exp = 0; \
++	unsigned short expsign = 1; \
++	unsigned long exp2 = 1; \
++	while (strpart && *strpart) \
++	{ \
++		switch (state) \
++		{ \
++			case -1: \
++				if (*strpart == 'x' || *strpart == 'X') \
++					state = 0; \
++				else if (*strpart == '+') \
++					negative = 0; \
++				else if (*strpart == '-') \
++					negative = 1; \
++				break; \
++			case 0: \
++				if (*strpart == '.') \
++				{ \
++					state = 1; \
++					break; \
++				} \
++				else if ((*strpart >= '0' && *strpart <= '9') || (*strpart >= 'a' && *strpart <= 'f') || (*strpart >= 'A' && *strpart <= 'F')) \
++					r *= 16.0; \
++			case 1: \
++				if (state == 1) \
++					rdiv *= 16; \
++				if ((*strpart == 'p') || (*strpart == 'P')) \
++					state = 2; \
++				else if (*strpart >= '0' && *strpart <= '9') \
++					r += ((double) (*strpart - '0')) / ((double) rdiv); \
++				else if (*strpart >= 'a' && *strpart <= 'f') \
++					r += ((double) (*strpart - 'a' + 0xA)) / ((double) rdiv); \
++				else if (*strpart >= 'A' && *strpart <= 'F') \
++					r += ((double) (*strpart - 'A' + 0xA)) / ((double) rdiv); \
++				break; \
++			case 2: \
++				if (*strpart == '+') \
++					expsign = 1; \
++				else if (*strpart == '-') \
++					expsign = -1; \
++				if ((*strpart) >= '0' && (*strpart) <= '9') \
++				{ \
++					exp *= 10; \
++					exp += (*strpart - '0'); \
++				} \
++				break; \
++		} \
++		((unsigned long) (strpart))++; \
++	} \
++	while (exp) \
++	{ \
++		exp2 *= 2; \
++		exp--; \
++	} \
++	if (expsign == 1) \
++		r *= (double) exp2; \
++	else \
++		r /= (double) exp2; \
++	if (negative) \
++		r = -r; \
++    if (!finite(r)) {sorry("floating point constant too large for host double"); abort();} \
++	sprintf (tempstr, "%.32e", r); \
++	res = REAL_VALUE_DTOF (tempstr, mode); \
++	res; \
++})
++
++#undef REAL_ARITHMETIC
++#define REAL_ARITHMETIC(value, code, d1, d2) \
++	real_arithmetic (&(value), (code), &(d1), &(d2))
++
++#undef REAL_VALUE_NEGATE
++#define REAL_VALUE_NEGATE(x) \
++__extension__ ({ \
++	REAL_VALUE_TYPE __tempx = x; \
++	if ((!(REAL_VALUE_ISNANUINF (__tempx))) && ((__tempx.mantissa) || (__tempx.exponent != 0x4000))) \
++		__tempx.exponent ^= 0x8000; \
++	__tempx; \
++})
++
++#undef REAL_VALUE_TRUNCATE
++#define REAL_VALUE_TRUNCATE(mode,x) \
++	(x)
++
++#define REAL_VALUE_TO_INT ereal_to_int
++
++#define REAL_VALUE_FROM_INT(d, lo, hi, mode) \
++	ereal_from_int (&d, (HOST_WIDE_INT) (lo), (HOST_WIDE_INT) (hi), mode)
++
++#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
++	ereal_from_uint (&d, lo, hi, mode)
++
++#undef REAL_VALUE_TO_TARGET_SINGLE
++#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
++	abort();
++
++#undef REAL_VALUE_TO_TARGET_DOUBLE
++#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
++	abort();
++
++#undef REAL_VALUE_TO_TARGET_LONG_DOUBLE
++#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
++do { \
++	REAL_VALUE_TYPE f = (IN); \
++	(OUT)[0] = f.exponent * 0x10000 + ((unsigned short) (f.mantissa / 0x1000000000000)), (OUT)[1] = (unsigned long) (f.mantissa / 0x10000), (OUT)[2] = ((unsigned short) (f.mantissa)) * 0x10000; \
++} while (0)
++
++#undef REAL_VALUE_TO_TARGET_SMAP_BCD
++#define REAL_VALUE_TO_TARGET_SMAP_BCD(IN, OUT) \
++do { \
++	REAL_VALUE_TYPE f = (IN); \
++	(OUT)[0] = f.exponent, (OUT)[1] = (unsigned long) (f.mantissa / 0x100000000), (OUT)[2] = (unsigned long) (f.mantissa); \
++} while (0)
++
++#define REAL_VALUE_TO_STRING(IN, OUT) \
++do { \
++	REAL_VALUE_TYPE f = (IN); \
++	if (REAL_VALUE_ISFINITE (f)) \
++	{ \
++		long exp; \
++		int neg = REAL_VALUE_ISNEGATIVE (f); \
++		if (neg) \
++			exp = f.exponent - 0xC000; \
++		else \
++			exp = f.exponent - 0x4000; \
++		sprintf ((OUT), "%s0.%08lx%08lxe%d\n", neg ? "-" : "", (unsigned long) (f.mantissa / 0x100000000), (unsigned long) (f.mantissa), (short) (exp + 1)); \
++	} \
++	else \
++		sprintf ((OUT), "Error"); \
++} while (0)
++
++#define REAL_VALUE_ABS(x) ((REAL_VALUE_ISNEGATIVE((x))\
++                            || REAL_VALUE_MINUS_ZERO((x))\
++                            || REAL_VALUES_IDENTICAL ((x), NEGATIVE_INF))?\
++                           REAL_VALUE_NEGATE((x)):(x))
++
++/* WARNING: This is the number of bits we can represent, not the true size of
++            the mantissa. */
++#define significand_size(dummy) (53)
++
++#undef MODE_HAS_NANS
++#define MODE_HAS_NANS(MODE) ((MODE)==BFmode)
++
++#undef MODE_HAS_INFINITIES
++#define MODE_HAS_INFINITIES(MODE) ((MODE)==BFmode)
++
++/* FIXME: GCC expects this to mean that there is only 0 and -0. We actually have
++          0, +0 and -0. This allows a few optimizations GCC is too cautious to
++          do in the presence of signed zeros. */
++#undef MODE_HAS_SIGNED_ZEROS
++#define MODE_HAS_SIGNED_ZEROS(MODE) ((MODE)==BFmode)
++
++/* end of smapbcd.h */
+diff -Naur gcc-3.3.3.orig/gcc/cppdefault.c gcc-3.3.3.tigcc8/gcc/cppdefault.c
+--- gcc-3.3.3.orig/gcc/cppdefault.c	Thu Nov  6 23:13:30 2003
++++ gcc-3.3.3.tigcc8/gcc/cppdefault.c	Thu Feb 19 21:20:02 2004
+@@ -31,6 +31,7 @@
+ = INCLUDE_DEFAULTS;
+ #else
+ = {
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+ #ifdef GPLUSPLUS_INCLUDE_DIR
+     /* Pick up GNU C++ generic include files.  */
+     { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
+@@ -70,11 +71,12 @@
+     /* /usr/include comes dead last.  */
+     { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 1 },
+ #endif
++#endif /* 0 */
+     { 0, 0, 0, 0, 0 }
+   };
+ #endif /* no INCLUDE_DEFAULTS */
+ 
+-#ifdef GCC_INCLUDE_DIR
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+ const char cpp_GCC_INCLUDE_DIR[] = GCC_INCLUDE_DIR;
+ const size_t cpp_GCC_INCLUDE_DIR_len = sizeof GCC_INCLUDE_DIR - 8;
+ #else
+diff -Naur gcc-3.3.3.orig/gcc/cppexp.c gcc-3.3.3.tigcc8/gcc/cppexp.c
+--- gcc-3.3.3.orig/gcc/cppexp.c	Sun Aug  3 17:58:06 2003
++++ gcc-3.3.3.tigcc8/gcc/cppexp.c	Thu Feb 19 21:20:02 2004
+@@ -178,6 +178,13 @@
+ 	  radix = 16;
+ 	  str++;
+ 	}
++      /* Require at least one binary digit to classify it as binary.  */
++      else if ((*str == 'b' || *str == 'B') && (str[1]=='0' || str[1]=='1'))
++	{
++	  radix = 2;
++	  str++;
++	}
++
+     }
+ 
+   /* Now scan for a well-formed integer or float.  */
+@@ -212,11 +219,15 @@
+ 	}
+     }
+ 
+-  if (float_flag != NOT_FLOAT && radix == 8)
++  if ((float_flag != NOT_FLOAT || CPP_OPTION(pfile,no_auto_octals)) && radix == 8)
+     radix = 10;
+ 
+-  if (max_digit >= radix)
+-    SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
++  if (max_digit >= radix) {
++    if (radix == 2)
++      SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
++    else
++      SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
++  }
+ 
+   if (float_flag != NOT_FLOAT)
+     {
+@@ -298,6 +309,8 @@
+     result |= CPP_N_DECIMAL;
+   else if (radix == 16)
+     result |= CPP_N_HEX;
++  else if (radix == 2)
++    result |= CPP_N_BINARY;
+   else
+     result |= CPP_N_OCTAL;
+ 
+@@ -348,6 +361,11 @@
+       else if ((type & CPP_N_RADIX) == CPP_N_HEX)
+ 	{
+ 	  base = 16;
++	  p += 2;
++	}
++      else if ((type & CPP_N_RADIX) == CPP_N_BINARY)
++	{
++	  base = 2;
+ 	  p += 2;
+ 	}
+ 
+diff -Naur gcc-3.3.3.orig/gcc/cpphash.h gcc-3.3.3.tigcc8/gcc/cpphash.h
+--- gcc-3.3.3.orig/gcc/cpphash.h	Tue Dec  2 01:56:18 2003
++++ gcc-3.3.3.tigcc8/gcc/cpphash.h	Thu Feb 19 21:20:02 2004
+@@ -385,6 +385,11 @@
+   /* Error counter for exit code.  */
+   unsigned int errors;
+ 
++  /* Line and column where a newline was first seen in a string
++     constant (multi-line strings).  */
++  unsigned int mls_line;
++  unsigned int mls_col;
++
+   /* Buffer to hold macro definition string.  */
+   unsigned char *macro_buffer;
+   unsigned int macro_buffer_len;
+diff -Naur gcc-3.3.3.orig/gcc/cppinit.c gcc-3.3.3.tigcc8/gcc/cppinit.c
+--- gcc-3.3.3.orig/gcc/cppinit.c	Tue Nov 18 22:23:46 2003
++++ gcc-3.3.3.tigcc8/gcc/cppinit.c	Thu Feb 19 21:20:02 2004
+@@ -543,6 +543,7 @@
+   CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int);
+   CPP_OPTION (pfile, unsigned_char) = 0;
+   CPP_OPTION (pfile, unsigned_wchar) = 1;
++  CPP_OPTION (pfile, no_auto_octals) = 0; /* (TIGCC) */
+ 
+   /* Initialize the line map.  Start at logical line 1, so we can use
+      a line number of zero for special states.  */
+@@ -982,7 +983,9 @@
+   _cpp_init_hashtable (pfile, table);
+ 
+   /* Set up the include search path now.  */
+-  if (! CPP_OPTION (pfile, no_standard_includes))
++  /* (TIGCC 20031007) We don't want any "standard" include directories.
++                      -- Kevin Kofler  */
++  if (0 /*! CPP_OPTION (pfile, no_standard_includes)*/)
+     init_standard_includes (pfile);
+ 
+   merge_include_chains (pfile);
+diff -Naur gcc-3.3.3.orig/gcc/cpplex.c gcc-3.3.3.tigcc8/gcc/cpplex.c
+--- gcc-3.3.3.orig/gcc/cpplex.c	Fri Sep 27 00:25:12 2002
++++ gcc-3.3.3.tigcc8/gcc/cpplex.c	Thu Feb 19 21:20:02 2004
+@@ -75,6 +75,7 @@
+ static void parse_number PARAMS ((cpp_reader *, cpp_string *, int));
+ static int unescaped_terminator_p PARAMS ((cpp_reader *, const uchar *));
+ static void parse_string PARAMS ((cpp_reader *, cpp_token *, cppchar_t));
++static void unterminated PARAMS ((cpp_reader *, int));
+ static bool trigraph_p PARAMS ((cpp_reader *));
+ static void save_comment PARAMS ((cpp_reader *, cpp_token *, const uchar *,
+ 				  cppchar_t));
+@@ -597,6 +598,22 @@
+     }
+ }
+ 
++/* Subroutine of parse_string.  Emits error for unterminated strings.  */
++static void
++unterminated (pfile, term)
++     cpp_reader *pfile;
++     int term;
++{
++  cpp_error (pfile, DL_ERROR, "missing terminating %c character", term);
++
++  if (term == '\"' && pfile->mls_line && pfile->mls_line != pfile->line)
++    {
++      cpp_error_with_line (pfile, DL_ERROR, pfile->mls_line, pfile->mls_col,
++			   "possible start of unterminated string literal");
++      pfile->mls_line = 0;
++    }
++}
++
+ /* Subroutine of parse_string.  */
+ static int
+ unescaped_terminator_p (pfile, dest)
+@@ -623,6 +640,7 @@
+    name.  Handles embedded trigraphs and escaped newlines.  The stored
+    string is guaranteed NUL-terminated, but it is not guaranteed that
+    this is the first NUL since embedded NULs are preserved.
++   Multi-line strings are allowed as a TIGCC extension (deprecated in the FSF GCC).
+ 
+    When this function returns, buffer->cur points to the next
+    character to be processed.  */
+@@ -689,21 +707,43 @@
+ 	}
+       else if (is_vspace (c))
+ 	{
+-	  /* No string literal may extend over multiple lines.  In
+-	     assembly language, suppress the error except for <>
+-	     includes.  This is a kludge around not knowing where
+-	     comments are.  */
+-	unterminated:
+-	  if (CPP_OPTION (pfile, lang) != CLK_ASM || terminator == '>')
+-	    cpp_error (pfile, DL_ERROR, "missing terminating %c character",
+-		       (int) terminator);
+-	  buffer->cur--;
+-	  break;
++	  /* In assembly language, silently terminate string and
++	     character literals at end of line.  This is a kludge
++	     around not knowing where comments are.  */
++	  if (CPP_OPTION (pfile, lang) == CLK_ASM && terminator != '>')
++	    {
++	      buffer->cur--;
++	      break;
++	    }
++
++	  /* Character constants and header names may not extend over
++	     multiple lines.  In Standard C, neither may strings.
++	     In TIGCC, we accept multiline strings as an
++	     extension, except in #include family directives.  */
++	  if (terminator != '"' || pfile->state.angled_headers)
++	    {
++	      unterminated (pfile, terminator);
++	      buffer->cur--;
++	      break;
++	    }
++
++	  if (pfile->mls_line == 0)
++	    {
++	      pfile->mls_line = token->line;
++	      pfile->mls_col = token->col;
++	    }
++	      
++	  handle_newline (pfile);
++	  c = '\n';
+ 	}
+       else if (c == '\0')
+ 	{
+ 	  if (buffer->cur - 1 == buffer->rlimit)
+-	    goto unterminated;
++	    {
++	      unterminated (pfile, terminator);
++	      buffer->cur--;
++	      break;
++	    }
+ 	  if (!warned_nulls)
+ 	    {
+ 	      warned_nulls = true;
+diff -Naur gcc-3.3.3.orig/gcc/cpplib.c gcc-3.3.3.tigcc8/gcc/cpplib.c
+--- gcc-3.3.3.orig/gcc/cpplib.c	Thu Sep 25 01:52:30 2003
++++ gcc-3.3.3.tigcc8/gcc/cpplib.c	Thu Feb 19 21:20:02 2004
+@@ -1076,6 +1076,7 @@
+      cpp_reader *pfile;
+ {
+   /* Pragmas in the global namespace.  */
++  cpp_register_pragma (pfile, 0, "poison", do_pragma_poison); /* (TIGCC) */
+   cpp_register_pragma (pfile, 0, "once", do_pragma_once);
+ 
+   /* New GCC-specific pragmas should be put in the GCC namespace.  */
+diff -Naur gcc-3.3.3.orig/gcc/cpplib.h gcc-3.3.3.tigcc8/gcc/cpplib.h
+--- gcc-3.3.3.orig/gcc/cpplib.h	Thu Nov  6 23:13:30 2003
++++ gcc-3.3.3.tigcc8/gcc/cpplib.h	Thu Feb 19 21:20:02 2004
+@@ -379,6 +379,9 @@
+   /* True for traditional preprocessing.  */
+   unsigned char traditional;
+ 
++  /* (TIGCC) True if numbers starting with zero should NOT be octal. */
++  unsigned char no_auto_octals;
++
+   /* Dependency generation.  */
+   struct
+   {
+@@ -630,6 +633,7 @@
+ #define CPP_N_DECIMAL	0x0100
+ #define CPP_N_HEX	0x0200
+ #define CPP_N_OCTAL	0x0400
++#define CPP_N_BINARY	0x0800
+ 
+ #define CPP_N_UNSIGNED	0x1000	/* Properties.  */
+ #define CPP_N_IMAGINARY	0x2000
+diff -Naur gcc-3.3.3.orig/gcc/cppmacro.c gcc-3.3.3.tigcc8/gcc/cppmacro.c
+--- gcc-3.3.3.orig/gcc/cppmacro.c	Thu Jun 19 07:40:28 2003
++++ gcc-3.3.3.tigcc8/gcc/cppmacro.c	Thu Feb 19 21:20:02 2004
+@@ -816,6 +816,11 @@
+   macro_arg *arg;
+   _cpp_buff *buff;
+ 
++  /* (TIGCC) If 'SYMSTR' is used with a string literal, it should be
++             converted automatically to 'SYMSTR_CONST'.  */
++  cpp_hashnode *orig_node=node; /* save the original node in case we change it */
++  symstr_const: /* start again from here after changing SYMSTR to SYMSTR_CONST */
++
+   /* First, fully macro-expand arguments, calculating the number of
+      tokens in the final expansion as we go.  The ordering of the if
+      statements below is subtle; we must handle stringification before
+@@ -849,6 +854,33 @@
+ 	  }
+       }
+ 
++  if (!ustrcmp (node->ident.str, U"SYMSTR"))
++  {
++    /* Accept one or more literal strings. If there are multiple ones, they
++       concatenate. Ignore any padding.
++       Refuse any other argument type. */
++    unsigned int i;
++    cpp_hashnode *newnode;
++
++    for (i=0;i<args->expanded_count;i++)
++    {
++      if ((args->expanded[i]->type != CPP_STRING)
++          && (args->expanded[i]->type != CPP_PADDING)) goto notconststring;
++    }
++
++    /* Change the macro to SYMSTR_CONST, if it is defined. */
++    newnode = cpp_lookup (pfile, U"SYMSTR_CONST",
++                          sizeof ("SYMSTR_CONST") - 1);
++    if (newnode->type == NT_MACRO) {
++      node = newnode;
++      macro = node->value.macro;
++      goto symstr_const; /* Start over from the beginning. */
++    }
++
++    notconststring:;
++  }
++  /* (END TIGCC) */
++
+   /* Now allocate space for the expansion, copy the tokens and replace
+      the arguments.  */
+   buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
+@@ -935,7 +967,10 @@
+     if (args[i].expanded)
+       free (args[i].expanded);
+ 
+-  push_ptoken_context (pfile, node, buff, first, dest - first);
++  push_ptoken_context (pfile, orig_node, buff, first, dest - first);
++  /* (TIGCC) Always use the ORIGINAL node here, not the modified one. Doing
++             otherwise would make subsequent expansions of SYMSTR fail after
++             the first conversion to SYMSTR_CONST. */
+ }
+ 
+ /* Return a special padding token, with padding inherited from SOURCE.  */
+diff -Naur gcc-3.3.3.orig/gcc/cppmain.c gcc-3.3.3.tigcc8/gcc/cppmain.c
+--- gcc-3.3.3.orig/gcc/cppmain.c	Sun Sep 14 15:26:36 2003
++++ gcc-3.3.3.tigcc8/gcc/cppmain.c	Thu Feb 19 21:20:02 2004
+@@ -177,7 +177,8 @@
+       pfile->print.prev = token;
+       cpp_output_token (token, pfile->print.outf);
+ 
+-      if (token->type == CPP_COMMENT)
++      if (token->type == CPP_STRING || token->type == CPP_WSTRING
++	  || token->type == CPP_COMMENT)
+ 	account_for_newlines (pfile, token->val.str.text, token->val.str.len);
+     }
+ }
+diff -Naur gcc-3.3.3.orig/gcc/diagnostic.c gcc-3.3.3.tigcc8/gcc/diagnostic.c
+--- gcc-3.3.3.orig/gcc/diagnostic.c	Thu May 29 21:09:54 2003
++++ gcc-3.3.3.tigcc8/gcc/diagnostic.c	Thu Feb 19 21:20:02 2004
+@@ -1205,9 +1205,7 @@
+   VA_CLOSE (ap);
+ 
+   fnotice (stderr,
+-"Please submit a full bug report,\n\
+-with preprocessed source if appropriate.\n\
+-See %s for instructions.\n", bug_report_url);
++"Please fill out a bug report form at %s.\n", bug_report_url);
+   exit (FATAL_EXIT_CODE);
+ }
+ 
+diff -Naur gcc-3.3.3.orig/gcc/dwarf2out.c gcc-3.3.3.tigcc8/gcc/dwarf2out.c
+--- gcc-3.3.3.orig/gcc/dwarf2out.c	Wed Oct  1 18:58:30 2003
++++ gcc-3.3.3.tigcc8/gcc/dwarf2out.c	Thu Feb 19 21:20:02 2004
+@@ -9125,6 +9125,10 @@
+ 		REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array);
+ 		break;
+ 
++	      case BFmode:
++		REAL_VALUE_TO_TARGET_SMAP_BCD (rv, array);
++		break;
++
+ 	      default:
+ 		abort ();
+ 	      }
+diff -Naur gcc-3.3.3.orig/gcc/emit-rtl.c gcc-3.3.3.tigcc8/gcc/emit-rtl.c
+--- gcc-3.3.3.orig/gcc/emit-rtl.c	Wed Dec 10 17:37:18 2003
++++ gcc-3.3.3.tigcc8/gcc/emit-rtl.c	Thu Feb 19 21:20:02 2004
+@@ -247,8 +247,8 @@
+     return (CONST_DOUBLE_LOW (a) == CONST_DOUBLE_LOW (b)
+ 	    && CONST_DOUBLE_HIGH (a) == CONST_DOUBLE_HIGH (b));
+   else
+-    return real_identical (CONST_DOUBLE_REAL_VALUE (a),
+-			   CONST_DOUBLE_REAL_VALUE (b));
++    return REAL_VALUES_IDENTICAL (*CONST_DOUBLE_REAL_VALUE (a),
++			   *CONST_DOUBLE_REAL_VALUE (b));
+ }
+ 
+ /* Returns a hash code for X (which is a really a mem_attrs *).  */
+@@ -1035,6 +1035,7 @@
+ 	}
+     }
+ 
++#if 0
+   /* The floating-point emulator can handle all conversions between
+      FP and integer operands.  This simplifies reload because it
+      doesn't have to deal with constructs like (subreg:DI
+@@ -1135,6 +1136,19 @@
+ 				 mode);
+ #endif
+     }
++#endif /* 0 */
++  else if (mode == BFmode
++	   && GET_CODE (x) == CONST_INT)
++    {
++      REAL_VALUE_TYPE r;
++      HOST_WIDE_INT i;
++      char s[25];
++
++      i = INTVAL (x);
++      sprintf (s, "%ld", (long) i);
++      r = REAL_VALUE_ATOF (s, mode);
++      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
++    }
+ 
+   /* Otherwise, we can't do this.  */
+   return 0;
+@@ -1369,6 +1383,7 @@
+       && GET_MODE_SIZE (mode) == UNITS_PER_WORD)
+     return op;
+ 
++#if 0
+   /* The output is some bits, the width of the target machine's word.
+      A wider-word host can surely hold them in a CONST_INT. A narrower-word
+      host can't.  */
+@@ -1447,10 +1462,12 @@
+       else
+ 	abort ();
+     }
++#endif /* 0 */
+ 
+   /* Single word float is a little harder, since single- and double-word
+      values often do not have the same high-order bits.  We have already
+      verified that we want the only defined word of the single-word value.  */
++#if 0
+   if (GET_MODE_CLASS (mode) == MODE_FLOAT
+       && GET_MODE_BITSIZE (mode) == 32
+       && GET_CODE (op) == CONST_DOUBLE)
+@@ -1474,6 +1491,7 @@
+ 
+       return GEN_INT (val);
+     }
++#endif /* 0 */
+ 
+   /* The only remaining cases that we can handle are integers.
+      Convert to proper endianness now since these cases need it.
+@@ -1553,10 +1571,63 @@
+       && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
+     return 0;
+ 
+-  /* If we want a word outside OP, return zero.  */
++  /* If we want a word outside OP, return zero, except for special BFmode cases. */
+   if (mode != BLKmode
+       && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
++  {
++  if (mode == BFmode)
++  {
++   if (GET_CODE (op) == MEM)
++    {
++      rtx addr = plus_constant (XEXP (op, 0), offset * UNITS_PER_WORD);
++      rtx new;
++
++      if (validate_address)
++	{
++	  if (reload_completed)
++	    {
++	      if (! strict_memory_address_p (HImode, addr))
++		return 0;
++	    }
++	  else
++	    addr = memory_address (HImode, addr);
++	}
++
++      new = gen_rtx_MEM (HImode, addr);
++
++      MEM_COPY_ATTRIBUTES (new, op);
++      RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
++
++      return new;
++    }
++  else if (GET_CODE (op) == REG)
++    {
++      if (REGNO (op) < FIRST_PSEUDO_REGISTER
++	  && REGNO (op) + offset >= FIRST_PSEUDO_REGISTER)
++	return 0;
++
++      if (REGNO (op) < FIRST_PSEUDO_REGISTER
++	  && (! HARD_REGNO_MODE_OK (REGNO (op), HImode)
++	      || ! HARD_REGNO_MODE_OK (REGNO (op) + offset, HImode)))
++	return 0;
++      else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
++	       || (REG_FUNCTION_VALUE_P (op)
++		   && rtx_equal_function_value_matters)
++	       || op == frame_pointer_rtx
++#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
++	       || op == arg_pointer_rtx
++#endif
++	       || op == stack_pointer_rtx)
++	return gen_rtx_SUBREG (HImode, op, offset);
++      else
++	return gen_rtx_REG (HImode, REGNO (op) + offset);
++    }
++  else if (GET_CODE (op) == SUBREG)
++    return gen_rtx_SUBREG (HImode, SUBREG_REG (op), offset + SUBREG_BYTE (op) / UNITS_PER_WORD);
++  }
++  else
+     return const0_rtx;
++  }
+ 
+   /* Form a new MEM at the requested address.  */
+   if (GET_CODE (op) == MEM)
+diff -Naur gcc-3.3.3.orig/gcc/explow.c gcc-3.3.3.tigcc8/gcc/explow.c
+--- gcc-3.3.3.orig/gcc/explow.c	Wed Dec 24 16:04:46 2003
++++ gcc-3.3.3.tigcc8/gcc/explow.c	Thu Feb 19 21:20:02 2004
+@@ -738,6 +738,10 @@
+ {
+   rtx temp = gen_reg_rtx (mode);
+ 
++  if (GET_MODE (x) == BFmode && mode != BFmode)
++    convert_move (x, temp, 0);
++  else
++  {
+   /* If not an operand, must be an address with PLUS and MULT so
+      do the computation.  */
+   if (! general_operand (x, VOIDmode))
+@@ -747,6 +751,7 @@
+     abort ();
+   if (x != temp)
+     emit_move_insn (temp, x);
++  }
+   return temp;
+ }
+ 
+diff -Naur gcc-3.3.3.orig/gcc/expr.c gcc-3.3.3.tigcc8/gcc/expr.c
+--- gcc-3.3.3.orig/gcc/expr.c	Tue Dec 23 18:40:40 2003
++++ gcc-3.3.3.tigcc8/gcc/expr.c	Thu Feb 19 21:20:02 2004
+@@ -644,6 +644,13 @@
+ 	  return;
+ 	}
+ #endif
++#ifdef HAVE_truncbfqf2
++      if (HAVE_truncbfqf2 && from_mode == BFmode && to_mode == QFmode)
++	{
++	  emit_unop_insn (CODE_FOR_truncbfqf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
+ #ifdef HAVE_truncxfqf2
+       if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode)
+ 	{
+@@ -680,6 +687,13 @@
+ 	  return;
+ 	}
+ #endif
++#ifdef HAVE_truncbfhf2
++      if (HAVE_truncbfhf2 && from_mode == BFmode && to_mode == HFmode)
++	{
++	  emit_unop_insn (CODE_FOR_truncbfhf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
+ #ifdef HAVE_truncxfhf2
+       if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode)
+ 	{
+@@ -709,6 +723,13 @@
+ 	  return;
+ 	}
+ #endif
++#ifdef HAVE_truncbftqf2
++      if (HAVE_truncbftqf2 && from_mode == BFmode && to_mode == TQFmode)
++	{
++	  emit_unop_insn (CODE_FOR_truncbftqf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
+ #ifdef HAVE_truncxftqf2
+       if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode)
+ 	{
+@@ -731,6 +752,13 @@
+ 	  return;
+ 	}
+ #endif
++#ifdef HAVE_truncbfsf2
++      if (HAVE_truncbfsf2 && from_mode == BFmode && to_mode == SFmode)
++	{
++	  emit_unop_insn (CODE_FOR_truncbfsf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
+ #ifdef HAVE_truncxfsf2
+       if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
+ 	{
+@@ -745,6 +773,13 @@
+ 	  return;
+ 	}
+ #endif
++#ifdef HAVE_truncbfdf2
++      if (HAVE_truncbfdf2 && from_mode == BFmode && to_mode == DFmode)
++	{
++	  emit_unop_insn (CODE_FOR_truncbfdf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
+ #ifdef HAVE_truncxfdf2
+       if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
+ 	{
+@@ -759,6 +794,20 @@
+ 	  return;
+ 	}
+ #endif
++#ifdef HAVE_truncxfbf2
++      if (HAVE_truncxfbf2 && from_mode == XFmode && to_mode == BFmode)
++	{
++	  emit_unop_insn (CODE_FOR_truncxfbf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
++#ifdef HAVE_trunctfbf2
++      if (HAVE_trunctfbf2 && from_mode == TFmode && to_mode == BFmode)
++	{
++	  emit_unop_insn (CODE_FOR_trunctfbf2, to, from, UNKNOWN);
++	  return;
++	}
++#endif
+ 
+       libcall = (rtx) 0;
+       switch (from_mode)
+@@ -770,6 +819,10 @@
+ 	      libcall = extendsfdf2_libfunc;
+ 	      break;
+ 
++	    case BFmode:
++	      libcall = extendsfbf2_libfunc;
++	      break;
++
+ 	    case XFmode:
+ 	      libcall = extendsfxf2_libfunc;
+ 	      break;
+@@ -790,6 +843,10 @@
+ 	      libcall = truncdfsf2_libfunc;
+ 	      break;
+ 
++	    case BFmode:
++	      libcall = extenddfbf2_libfunc;
++	      break;
++
+ 	    case XFmode:
+ 	      libcall = extenddfxf2_libfunc;
+ 	      break;
+@@ -803,6 +860,22 @@
+ 	    }
+ 	  break;
+ 
++	case BFmode:
++	  switch (to_mode)
++	    {
++	    case SFmode:
++	      libcall = truncbfsf2_libfunc;
++	      break;
++
++	    case DFmode:
++	      libcall = truncbfdf2_libfunc;
++	      break;
++
++	    default:
++	      break;
++	    }
++	  break;
++
+ 	case XFmode:
+ 	  switch (to_mode)
+ 	    {
+@@ -814,6 +887,10 @@
+ 	      libcall = truncxfdf2_libfunc;
+ 	      break;
+ 
++	    case BFmode:
++	      libcall = truncxfbf2_libfunc;
++	      break;
++
+ 	    default:
+ 	      break;
+ 	    }
+@@ -1357,7 +1434,7 @@
+   if (GET_MODE (x) != VOIDmode)
+     oldmode = GET_MODE (x);
+ 
+-  if (mode == oldmode)
++  if (mode == oldmode || oldmode == BFmode)
+     return x;
+ 
+   /* There is one case that we must handle specially: If we are converting
+@@ -1940,7 +2017,9 @@
+   if (TARGET_MEM_FUNCTIONS)
+     size_mode = TYPE_MODE (sizetype);
+   else
+-    size_mode = TYPE_MODE (unsigned_type_node);
++    /* TIGCC Patch: The bcopy libcall expects short integers even with
++       -mlong.  */
++    size_mode = TYPE_MODE (short_unsigned_type_node);
+   size = convert_to_mode (size_mode, size, 1);
+   size = copy_to_mode_reg (size_mode, size);
+ 
+@@ -1950,15 +2029,19 @@
+      targets where libcalls and normal calls have different conventions
+      for returning pointers, we could end up generating incorrect code.
+ 
+-     For convenience, we generate the call to bcopy this way as well.  */
++     For convenience, we generate the call to bcopy this way as well.
++     (TIGCC 20030315) NO, we CANNOT, because this generates incorrect code!  */
+ 
+   dst_tree = make_tree (ptr_type_node, dst);
+   src_tree = make_tree (ptr_type_node, src);
+   if (TARGET_MEM_FUNCTIONS)
+     size_tree = make_tree (sizetype, size);
+   else
+-    size_tree = make_tree (unsigned_type_node, size);
++    /* TIGCC Patch: The bcopy libcall expects short integers even with
++       -mlong.  */
++    size_tree = make_tree (short_unsigned_type_node, size);
+ 
++#if 0
+   fn = emit_block_move_libcall_fn (true);
+   arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
+   if (TARGET_MEM_FUNCTIONS)
+@@ -1979,6 +2062,13 @@
+   TREE_SIDE_EFFECTS (call_expr) = 1;
+ 
+   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
++#endif /* 0 */
++
++  emit_library_call (bcopy_libfunc, LCT_NORMAL,
++                     VOIDmode, 3, src, Pmode, dst, Pmode,
++                     convert_to_mode (TYPE_MODE (short_integer_type_node), size,
++                                      TREE_UNSIGNED (short_integer_type_node)),
++                                      TYPE_MODE (short_integer_type_node));
+ 
+   /* If we are initializing a readonly value, show the above call
+      clobbered it.  Otherwise, a load from it may erroneously be
+@@ -2014,8 +2104,10 @@
+       else
+ 	{
+ 	  fn = get_identifier ("bcopy");
++      /* TIGCC Patch: The bcopy libcall expects short integers even with
++         -mlong.  */
+ 	  args = build_function_type_list (void_type_node, const_ptr_type_node,
+-					   ptr_type_node, unsigned_type_node,
++					   ptr_type_node, short_unsigned_type_node,
+ 					   NULL_TREE);
+ 	}
+ 
+@@ -3054,7 +3146,9 @@
+   if (TARGET_MEM_FUNCTIONS)
+     size_mode = TYPE_MODE (sizetype);
+   else
+-    size_mode = TYPE_MODE (unsigned_type_node);
++    /* TIGCC Patch: The bzero libcall expects short integers even with
++       -mlong.  */
++    size_mode = TYPE_MODE (short_unsigned_type_node);
+   size = convert_to_mode (size_mode, size, 1);
+   size = copy_to_mode_reg (size_mode, size);
+ 
+@@ -3064,14 +3158,18 @@
+      targets where libcalls and normal calls have different conventions
+      for returning pointers, we could end up generating incorrect code.
+ 
+-     For convenience, we generate the call to bzero this way as well.  */
++     For convenience, we generate the call to bzero this way as well.
++     (TIGCC 20030315) NO, we CANNOT, because this generates incorrect code!  */
+ 
+   object_tree = make_tree (ptr_type_node, object);
+   if (TARGET_MEM_FUNCTIONS)
+     size_tree = make_tree (sizetype, size);
+   else
+-    size_tree = make_tree (unsigned_type_node, size);
++    /* TIGCC Patch: The bzero libcall expects short integers even with
++       -mlong.  */
++    size_tree = make_tree (short_unsigned_type_node, size);
+ 
++#if 0
+   fn = clear_storage_libcall_fn (true);
+   arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
+   if (TARGET_MEM_FUNCTIONS)
+@@ -3085,6 +3183,11 @@
+   TREE_SIDE_EFFECTS (call_expr) = 1;
+ 
+   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
++#endif /* 0 */
++
++  emit_library_call (bzero_libfunc, LCT_NORMAL,
++                     VOIDmode, 2, object, Pmode, size,
++                     TYPE_MODE (short_integer_type_node));
+ 
+   /* If we are initializing a readonly value, show the above call
+      clobbered it.  Otherwise, a load from it may erroneously be
+@@ -3120,8 +3223,10 @@
+       else
+ 	{
+ 	  fn = get_identifier ("bzero");
++      /* TIGCC Patch: The bzero libcall expects short integers even with
++         -mlong.  */
+ 	  args = build_function_type_list (void_type_node, ptr_type_node,
+-					   unsigned_type_node, NULL_TREE);
++					   short_unsigned_type_node, NULL_TREE);
+ 	}
+ 
+       fn = build_decl (FUNCTION_DECL, fn, args);
+@@ -3522,6 +3627,9 @@
+ 
+   REAL_VALUE_FROM_CONST_DOUBLE (r, y);
+ 
++/* (TIGCC) We do not implement exact_real_truncate and there is no narrower
++           float mode anyway. -- Kevin Kofler */
++#if 0
+   for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
+        srcmode != orig_srcmode;
+        srcmode = GET_MODE_WIDER_MODE (srcmode))
+@@ -3561,6 +3669,7 @@
+ 
+       return last_insn;
+     }
++#endif /* 0 */
+ 
+   return NULL_RTX;
+ }
+@@ -3882,7 +3991,8 @@
+       int not_stack;
+       /* # words of start of argument
+ 	 that we must make space for but need not store.  */
+-      int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
++      /* (TIGCC) This code is trying to take a modulus by zero. */
++      int offset = 0 /* partial % (PARM_BOUNDARY / BITS_PER_WORD) */;
+       int args_offset = INTVAL (args_so_far);
+       int skip;
+ 
+@@ -4257,13 +4367,15 @@
+ 					    size, TREE_UNSIGNED (sizetype)),
+ 			   TYPE_MODE (sizetype));
+       else
++        /* TIGCC Patch: The bcopy libcall expects short integers even with
++           -mlong.  */
+         emit_library_call (bcopy_libfunc, LCT_NORMAL,
+ 			   VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
+ 			   XEXP (to_rtx, 0), Pmode,
+-			   convert_to_mode (TYPE_MODE (integer_type_node),
++			   convert_to_mode (TYPE_MODE (short_integer_type_node),
+ 					    size,
+-					    TREE_UNSIGNED (integer_type_node)),
+-			   TYPE_MODE (integer_type_node));
++					    TREE_UNSIGNED (short_integer_type_node)),
++			   TYPE_MODE (short_integer_type_node));
+ 
+       preserve_temp_slots (to_rtx);
+       free_temp_slots ();
+@@ -4692,7 +4804,7 @@
+ 	is_zeros_p (TREE_REALPART (exp)) && is_zeros_p (TREE_IMAGPART (exp));
+ 
+     case REAL_CST:
+-      return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0);
++      return REAL_VALUE_ISZERO (TREE_REAL_CST (exp));
+ 
+     case VECTOR_CST:
+       for (elt = TREE_VECTOR_CST_ELTS (exp); elt;
+diff -Naur gcc-3.3.3.orig/gcc/final.c gcc-3.3.3.tigcc8/gcc/final.c
+--- gcc-3.3.3.orig/gcc/final.c	Mon Dec  1 08:18:36 2003
++++ gcc-3.3.3.tigcc8/gcc/final.c	Sun Aug  8 12:11:32 2004
+@@ -2909,7 +2909,19 @@
+   /* simplify_subreg does not remove subreg from volatile references.
+      We are required to.  */
+   if (GET_CODE (y) == MEM)
+-    *xp = adjust_address (y, GET_MODE (x), SUBREG_BYTE (x));
++    {
++      /* (TIGCC 20030220) On big-endian machines, adjust offset of paradoxical
++                          subregs of memory to point to the correct place.
++                          I don't know for sure whether this is needed for the
++                          non-paradoxical case as well, but as far as I can
++                          tell, non-paradoxical memory subregs are simplified
++                          elsewhere than here. -- Kevin Kofler */
++      int x_size = GET_MODE_SIZE (GET_MODE (x));
++      int y_size = GET_MODE_SIZE (GET_MODE (y));
++      int offset = SUBREG_BYTE (x);
++      if (BYTES_BIG_ENDIAN && (x_size > y_size)) offset-=(x_size-y_size);
++      *xp = adjust_address (y, GET_MODE (x), offset);
++    }
+   else
+     {
+       rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
+@@ -3405,11 +3417,23 @@
+ 	    else if (letter == 'l')
+ 	      output_asm_label (operands[c]);
+ 	    else if (letter == 'a')
++	    {
+ 	      output_address (operands[c]);
++	      /* TIGCC Patch: This is a very bad try to implement addresses
++	         relative to a register.  See m68k.c
++	         (TIGCC 20040808) Added CONST here (and below) too. -- Kevin Kofler  */
++	      if (TARGET_REG_RELATIVE && (GET_CODE (operands[c]) == SYMBOL_REF || GET_CODE (operands[c]) == LABEL_REF || GET_CODE (operands[c]) == CODE_LABEL || GET_CODE (operands[c]) == CONST))
++		fprintf (asm_out_file, "-__relation(%%%s)", TARGET_RELATION_REG);
++	    }
+ 	    else if (letter == 'c')
+ 	      {
+ 		if (CONSTANT_ADDRESS_P (operands[c]))
++		{
+ 		  output_addr_const (asm_out_file, operands[c]);
++		  /* TIGCC Patch: See above  */
++		  if (TARGET_REG_RELATIVE && (GET_CODE (operands[c]) == SYMBOL_REF || GET_CODE (operands[c]) == LABEL_REF || GET_CODE (operands[c]) == CODE_LABEL || GET_CODE (operands[c]) == CONST))
++		    fprintf (asm_out_file, "-__relation(%%%s)", TARGET_RELATION_REG);
++		}
+ 		else
+ 		  output_operand (operands[c], 'c');
+ 	      }
+@@ -3422,6 +3446,9 @@
+ 		  {
+ 		    putc ('-', asm_out_file);
+ 		    output_addr_const (asm_out_file, operands[c]);
++		    /* TIGCC Patch: See above */
++		    if (TARGET_REG_RELATIVE && (GET_CODE (operands[c]) == SYMBOL_REF || GET_CODE (operands[c]) == LABEL_REF || GET_CODE (operands[c]) == CODE_LABEL))
++		      fprintf (asm_out_file, "-__relation(%%%s)", TARGET_RELATION_REG);
+ 		  }
+ 	      }
+ 	    else
+@@ -3939,6 +3966,8 @@
+     }
+   else
+     {
++      abort ();
++#if 0
+       REAL_VALUE_TYPE r;
+       long l[2];
+       REAL_VALUE_FROM_CONST_DOUBLE (r, value);
+@@ -3967,6 +3996,7 @@
+ 
+       *first = GEN_INT ((HOST_WIDE_INT) l[0]);
+       *second = GEN_INT ((HOST_WIDE_INT) l[1]);
++#endif /* 0 */
+     }
+ }
+ 
+diff -Naur gcc-3.3.3.orig/gcc/flags.h gcc-3.3.3.tigcc8/gcc/flags.h
+--- gcc-3.3.3.orig/gcc/flags.h	Fri Jun 20 23:18:40 2003
++++ gcc-3.3.3.tigcc8/gcc/flags.h	Tue Jul 27 12:34:52 2004
+@@ -690,4 +690,10 @@
+ #define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
+   (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
+ 
++/* (TIGCC) Make compound literals (cast constructors) global for backwards compatibility.  */
++extern int flag_global_compound_literals;
++
++/* (TIGCC 20040727) When merging constants, also merge constant pools.  */
++extern int flag_merge_constant_pools;
++
+ #endif /* ! GCC_FLAGS_H */
+diff -Naur gcc-3.3.3.orig/gcc/flow.c gcc-3.3.3.tigcc8/gcc/flow.c
+--- gcc-3.3.3.orig/gcc/flow.c	Wed Jul 30 02:57:24 2003
++++ gcc-3.3.3.tigcc8/gcc/flow.c	Thu Feb 19 21:20:02 2004
+@@ -2382,11 +2382,13 @@
+   if (n_basic_blocks == 0
+       || (regno < FIRST_PSEUDO_REGISTER
+ 	  && (global_regs[regno]
+-	      || fixed_regs[regno]
+-	      || FUNCTION_ARG_REGNO_P (regno))))
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++	      || fixed_regs[regno])))
+     return 0;
+ 
+-  return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno);
++  return (REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)
++	  && (regno >= FIRST_PSEUDO_REGISTER || ! function_arg_regno_p (regno)));
++/* end-TIGCC-local (regparms) */
+ }
+ 
+ /* 1 if register REGNO was alive at a place where `setjmp' was called
+@@ -2710,6 +2712,14 @@
+ #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+       && ! (regno_first == ARG_POINTER_REGNUM && fixed_regs[regno_first])
+ #endif
++/* (TIGCC 20030316) Applied the following proposed patch for PR 7871 (and 7595):
++
++        2003-03-10  James E Wilson  <wilson@tuliptree.org>
++ 
++            * flow.c (mark_set_1): Handle global_regs like the frame pointer.
++
++    -- Kevin Kofler  */
++      && ! (regno_first < FIRST_PSEUDO_REGISTER && global_regs[regno_first])
+       )
+     {
+       int some_was_live = 0, some_was_dead = 0;
+diff -Naur gcc-3.3.3.orig/gcc/fold-const.c gcc-3.3.3.tigcc8/gcc/fold-const.c
+--- gcc-3.3.3.orig/gcc/fold-const.c	Thu Jan  1 04:44:52 2004
++++ gcc-3.3.3.tigcc8/gcc/fold-const.c	Thu Feb 19 21:20:02 2004
+@@ -1244,7 +1244,7 @@
+       REAL_ARITHMETIC (value, code, d1, d2);
+ 
+       t = build_real (TREE_TYPE (arg1),
+-		      real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)),
++		      REAL_VALUE_TRUNCATE (TYPE_MODE (TREE_TYPE (arg1)),
+ 					   value));
+ 
+       TREE_OVERFLOW (t)
+@@ -1548,6 +1548,7 @@
+ 	  TREE_CONSTANT_OVERFLOW (t)
+ 	    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+ 	}
++#if 0
+       else if (TREE_CODE (arg1) == REAL_CST)
+ 	{
+ 	  /* Don't initialize these, use assignments.
+@@ -1591,6 +1592,7 @@
+ 	  TREE_CONSTANT_OVERFLOW (t)
+ 	    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+ 	}
++#endif /* 0 */
+       TREE_TYPE (t) = type;
+     }
+   else if (TREE_CODE (type) == REAL_TYPE)
+@@ -1609,7 +1611,7 @@
+ 	    }
+ 
+ 	  t = build_real (type,
+-			  real_value_truncate (TYPE_MODE (type),
++			  REAL_VALUE_TRUNCATE (TYPE_MODE (type),
+ 					       TREE_REAL_CST (arg1)));
+ 
+ 	  TREE_OVERFLOW (t)
+@@ -5041,7 +5043,11 @@
+ 		= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
+ 	    }
+ 	  else if (TREE_CODE (arg0) == REAL_CST)
+-	    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
++	    {
++	      REAL_VALUE_TYPE x = TREE_REAL_CST (arg0);
++	      x = REAL_VALUE_NEGATE (x);
++	      t = build_real (type, x);
++	    }
+ 	}
+       else if (TREE_CODE (arg0) == NEGATE_EXPR)
+ 	return TREE_OPERAND (arg0, 0);
+@@ -5086,9 +5092,10 @@
+ 	    }
+ 	  else if (TREE_CODE (arg0) == REAL_CST)
+ 	    {
+-	      if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
++	      REAL_VALUE_TYPE x = TREE_REAL_CST (arg0);
++	      if (REAL_VALUE_NEGATIVE (x))
+ 		t = build_real (type,
+-				REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
++				REAL_VALUE_NEGATE (x));
+ 	    }
+ 	}
+       else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
+diff -Naur gcc-3.3.3.orig/gcc/function.c gcc-3.3.3.tigcc8/gcc/function.c
+--- gcc-3.3.3.orig/gcc/function.c	Thu Dec 11 07:57:54 2003
++++ gcc-3.3.3.tigcc8/gcc/function.c	Thu Feb 19 21:20:04 2004
+@@ -454,8 +454,25 @@
+   f->x_nonlocal_goto_stack_level = NULL;
+   f->x_cleanup_label = NULL;
+   f->x_return_label = NULL;
++#if 0 /* (TIGCC 20030607) Revert the following patch:
++
++2003-03-21  Richard Henderson  <rth@redhat.com>
++
++	PR opt/2001
++	* bb-reorder.c (maybe_duplicate_computed_goto_succ): New.
++	(make_reorder_chain_1): Call it.
++
++	* function.h (struct function): Add computed_goto_common_label,
++	computed_goto_common_reg.
++	* function.c (free_after_compilation): Zap them.
++	* stmt.c (expand_computed_goto): Use them to produce one
++	indirect branch per function.
++
++because it breaks ER_throw, whereas PR opt/2001 is a compilation slowness
++problem (in an extreme case) only.  -- Kevin Kofler  */
+   f->computed_goto_common_label = NULL;
+   f->computed_goto_common_reg = NULL;
++#endif /* 0 */
+   f->x_save_expr_regs = NULL;
+   f->x_stack_slot_list = NULL;
+   f->x_rtl_expr_chain = NULL;
+@@ -8004,3 +8021,29 @@
+ }
+ 
+ #include "gt-function.h"
++
++/* begin-TIGCC-local (regparms): explicit register specification for parameters */
++/* Return 1 if an argument for the current function was passed in
++   register REGNO.  */
++
++int
++function_arg_regno_p (regno)
++     int regno;
++{
++  tree parm = DECL_ARGUMENTS (current_function_decl);
++  for (; parm; parm = TREE_CHAIN (parm))
++    {
++      rtx incoming = DECL_INCOMING_RTL (parm);
++      if (GET_CODE (incoming) == REG)
++	{
++	  int incoming_reg;
++	  incoming_reg = REGNO (incoming);
++	  if (regno >= incoming_reg &&
++	      regno < incoming_reg + HARD_REGNO_NREGS (incoming_reg,
++						       GET_MODE (incoming)))
++	    return 1;
++	}
++    }
++  return 0;
++}
++/* end-TIGCC-local (regparms) */
+diff -Naur gcc-3.3.3.orig/gcc/function.h gcc-3.3.3.tigcc8/gcc/function.h
+--- gcc-3.3.3.orig/gcc/function.h	Fri Nov 14 06:46:08 2003
++++ gcc-3.3.3.tigcc8/gcc/function.h	Thu Feb 19 21:20:04 2004
+@@ -273,9 +273,28 @@
+      on machines which require execution of the epilogue on all returns.  */
+   rtx x_return_label;
+ 
+-  /* Label and register for unswitching computed gotos.  */
++/* (TIGCC 20030607) Revert the following patch:
++
++2003-03-21  Richard Henderson  <rth@redhat.com>
++
++	PR opt/2001
++	* bb-reorder.c (maybe_duplicate_computed_goto_succ): New.
++	(make_reorder_chain_1): Call it.
++
++	* function.h (struct function): Add computed_goto_common_label,
++	computed_goto_common_reg.
++	* function.c (free_after_compilation): Zap them.
++	* stmt.c (expand_computed_goto): Use them to produce one
++	indirect branch per function.
++
++because it breaks ER_throw, whereas PR opt/2001 is a compilation slowness
++problem (in an extreme case) only.  -- Kevin Kofler
++
++  ** Label and register for unswitching computed gotos.  **
+   rtx computed_goto_common_label;
+   rtx computed_goto_common_reg;
++
++(END TIGCC 20030607) */
+ 
+   /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
+      So we can mark them all live at the end of the function, if nonopt.  */
+diff -Naur gcc-3.3.3.orig/gcc/gcc.c gcc-3.3.3.tigcc8/gcc/gcc.c
+--- gcc-3.3.3.orig/gcc/gcc.c	Sat Dec  6 03:53:02 2003
++++ gcc-3.3.3.tigcc8/gcc/gcc.c	Thu Feb 19 21:20:04 2004
+@@ -1326,6 +1326,7 @@
+ #define MD_STARTFILE_PREFIX_1 ""
+ #endif
+ 
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+ /* Supply defaults for the standard prefixes.  */
+ 
+ #ifndef STANDARD_EXEC_PREFIX
+@@ -1352,6 +1353,7 @@
+ static const char *tooldir_prefix;
+ 
+ static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
++#endif /* 0 */
+ 
+ /* Subdirectory to use for locating libraries.  Set by
+    set_multilib_dir based on the compilation options.  */
+@@ -1419,10 +1421,12 @@
+   INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
+   INIT_STATIC_SPEC ("linker",			&linker_name_spec),
+   INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+   INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
+   INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
+   INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
+   INIT_STATIC_SPEC ("startfile_prefix_spec",	&startfile_prefix_spec),
++#endif /* 0 */
+ };
+ 
+ #ifdef EXTRA_SPECS		/* additional specs needed */
+@@ -2869,8 +2873,10 @@
+ /* Used to track if none of the -B paths are used.  */
+ static int warn_B;
+ 
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+ /* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
+ static int *warn_std_ptr = 0;
++#endif /* 0 */
+ 
+ #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+ 
+@@ -3053,7 +3059,9 @@
+      const char *const *argv;
+ {
+   int i;
++#if 0 /* (TIGCC 20040104) Don't use environment variables. */
+   const char *temp;
++#endif /* 0 */
+   char *temp1;
+   const char *spec_lang = 0;
+   int last_language_n_infiles;
+@@ -3065,7 +3073,9 @@
+   int j;
+ #endif
+ 
++#if 0 /* (TIGCC 20040104) Don't use environment variables. */
+   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
++#endif /* 0 */
+ 
+   n_switches = 0;
+   n_infiles = 0;
+@@ -3142,7 +3152,7 @@
+   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
+      see if we can create it from the pathname specified in argv[0].  */
+ 
+-#ifndef VMS
++#if 0
+   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
+   if (!gcc_exec_prefix)
+     {
+@@ -3153,6 +3163,7 @@
+     }
+ #endif
+ 
++#if 0 /* (TIGCC 20040104) Don't use environment variables. */
+   if (gcc_exec_prefix)
+     {
+       int len = strlen (gcc_exec_prefix);
+@@ -3277,6 +3288,7 @@
+ 	    endp++;
+ 	}
+     }
++#endif /* 0 */
+ 
+   /* Convert new-style -- options to old-style.  */
+   translate_options (&argc, &argv);
+@@ -3673,11 +3685,12 @@
+ 
+   /* Set up the search paths before we go looking for config files.  */
+ 
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+   /* These come before the md prefixes so that we will find gcc's subcommands
+      (such as cpp) rather than those of the host system.  */
+   /* Use 2 as fourth arg meaning try just the machine as a suffix,
+      as well as trying the machine and the version.  */
+-#ifndef OS2
++#ifndef OS2                   
+   add_prefix (&exec_prefixes, standard_exec_prefix, "GCC",
+ 	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
+   add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
+@@ -3730,6 +3743,7 @@
+   add_prefix (&startfile_prefixes,
+ 	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
+ 	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
++#endif /* 0 */
+ 
+ #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
+   /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
+@@ -6057,6 +6071,7 @@
+   else
+     init_spec ();
+ 
++#if 0
+   /* We need to check standard_exec_prefix/just_machine_suffix/specs
+      for any override of as, ld and libraries.  */
+   specs_file = (char *) alloca (strlen (standard_exec_prefix)
+@@ -6068,7 +6083,9 @@
+   strcat (specs_file, "specs");
+   if (access (specs_file, R_OK) == 0)
+     read_specs (specs_file, TRUE);
++#endif
+ 
++#if 0 /* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
+   /* If not cross-compiling, look for executables in the standard
+      places.  */
+   if (*cross_compile == '0')
+@@ -6132,6 +6149,7 @@
+ 		  PREFIX_PRIORITY_LAST, 1, NULL, 0);
+ #endif
+     }
++#endif /* 0 */
+ 
+   /* Process any user specified specs in the order given on the command
+      line.  */
+@@ -6142,10 +6160,12 @@
+       read_specs (filename ? filename : uptr->filename, FALSE);
+     }
+ 
++#if 0 /* (TIGCC 20040104) Don't use environment variables. */
+   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
+   if (gcc_exec_prefix)
+     gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
+ 			      spec_version, dir_separator_str, NULL);
++#endif /* 0 */
+ 
+   /* Now we have the specs.
+      Set the `valid' bits for switches that match anything in any spec.  */
+@@ -6166,7 +6186,8 @@
+ 
+   if (print_search_dirs)
+     {
+-      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
++/* (TIGCC 20040104) Don't hardcode any prefix at compile time. */
++      printf (_("install: relocatable TIGCC installation\n"));
+       printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
+       printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
+       return (0);
+diff -Naur gcc-3.3.3.orig/gcc/gcse.c gcc-3.3.3.tigcc8/gcc/gcse.c
+--- gcc-3.3.3.orig/gcc/gcse.c	Sat Dec 20 19:59:50 2003
++++ gcc-3.3.3.tigcc8/gcc/gcse.c	Thu Feb 19 21:20:04 2004
+@@ -4327,11 +4327,14 @@
+   rtx newreg = NULL, newcnst = NULL;
+ 
+   /* Rule out USE instructions and ASM statements as we don't want to
+-     change the hard registers mentioned.  */
++     change the hard registers mentioned.
++     (TIGCC) The same thing goes for global register variables. CalcRogue gets
++             miscompiled without this patch.  */
+   if (GET_CODE (x) == REG
+       && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+           || (GET_CODE (PATTERN (insn)) != USE
+-	      && asm_noperands (PATTERN (insn)) < 0)))
++	      && asm_noperands (PATTERN (insn)) < 0
++	      && ! global_regs[REGNO (x)])))
+     {
+       cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
+       struct elt_loc_list *l;
+diff -Naur gcc-3.3.3.orig/gcc/ifcvt.c gcc-3.3.3.tigcc8/gcc/ifcvt.c
+--- gcc-3.3.3.orig/gcc/ifcvt.c	Sun Dec 21 16:08:04 2003
++++ gcc-3.3.3.tigcc8/gcc/ifcvt.c	Sat Sep 25 03:05:22 2004
+@@ -1688,6 +1688,16 @@
+   if (GET_CODE (op) == MEM)
+     return ! side_effects_p (XEXP (op, 0));
+ 
++  /* (TIGCC 20040925) Can't if-convert global register variables.
++                      -- Kevin Kofler */
++  if (GET_CODE (op) == REG)
++    {
++      int regno;
++      regno = REGNO (op);
++      if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
++        return FALSE;
++    }
++
+   if (side_effects_p (op))
+     return FALSE;
+ 
+@@ -2973,6 +2983,21 @@
+ 		 TEST range.  */
+ 	      if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
+ 		return FALSE;
++
++	      /* (TIGCC 20040925) Can't if-convert global register variables.
++	                          -- Kevin Kofler */
++	      if (GET_CODE (PATTERN (insn)) == SET)
++            {
++              rtx dest;
++              dest = SET_DEST (PATTERN (insn));
++              if (GET_CODE (dest) == REG)
++                {
++                  int regno;
++                  regno = REGNO (dest);
++                  if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
++                    return FALSE;
++                }
++            }
+ 	    }
+ 	  if (insn == end)
+ 	    break;
+diff -Naur gcc-3.3.3.orig/gcc/libfuncs.h gcc-3.3.3.tigcc8/gcc/libfuncs.h
+--- gcc-3.3.3.orig/gcc/libfuncs.h	Tue Jun  4 09:07:50 2002
++++ gcc-3.3.3.tigcc8/gcc/libfuncs.h	Thu Feb 19 21:20:04 2004
+@@ -25,16 +25,22 @@
+ enum libfunc_index
+ {
+   LTI_extendsfdf2,
++  LTI_extendsfbf2,
+   LTI_extendsfxf2,
+   LTI_extendsftf2,
++  LTI_extenddfbf2,
+   LTI_extenddfxf2,
+   LTI_extenddftf2,
++  LTI_extendbfxf2,
+ 
+   LTI_truncdfsf2,
++  LTI_truncbfsf2,
+   LTI_truncxfsf2,
+   LTI_trunctfsf2,
++  LTI_truncbfdf2,
+   LTI_truncxfdf2,
+   LTI_trunctfdf2,
++  LTI_truncxfbf2,
+ 
+   LTI_abort,
+   LTI_memcpy,
+@@ -76,6 +82,14 @@
+   LTI_ledf2,
+   LTI_unorddf2,
+ 
++  LTI_eqbf2,
++  LTI_nebf2,
++  LTI_gtbf2,
++  LTI_gebf2,
++  LTI_ltbf2,
++  LTI_lebf2,
++  LTI_unordbf2,
++
+   LTI_eqxf2,
+   LTI_nexf2,
+   LTI_gtxf2,
+@@ -100,6 +114,10 @@
+   LTI_floatdidf,
+   LTI_floattidf,
+ 
++  LTI_floatsibf,
++  LTI_floatdibf,
++  LTI_floattibf,
++
+   LTI_floatsixf,
+   LTI_floatdixf,
+   LTI_floattixf,
+@@ -116,6 +134,10 @@
+   LTI_fixdfdi,
+   LTI_fixdfti,
+ 
++  LTI_fixbfsi,
++  LTI_fixbfdi,
++  LTI_fixbfti,
++
+   LTI_fixxfsi,
+   LTI_fixxfdi,
+   LTI_fixxfti,
+@@ -132,6 +154,10 @@
+   LTI_fixunsdfdi,
+   LTI_fixunsdfti,
+ 
++  LTI_fixunsbfsi,
++  LTI_fixunsbfdi,
++  LTI_fixunsbfti,
++
+   LTI_fixunsxfsi,
+   LTI_fixunsxfdi,
+   LTI_fixunsxfti,
+@@ -152,16 +178,22 @@
+ 
+ /* Accessor macros for libfunc_table.  */
+ #define extendsfdf2_libfunc	(libfunc_table[LTI_extendsfdf2])
++#define extendsfbf2_libfunc	(libfunc_table[LTI_extendsfbf2])
+ #define extendsfxf2_libfunc	(libfunc_table[LTI_extendsfxf2])
+ #define extendsftf2_libfunc	(libfunc_table[LTI_extendsftf2])
++#define extenddfbf2_libfunc	(libfunc_table[LTI_extenddfbf2])
+ #define extenddfxf2_libfunc	(libfunc_table[LTI_extenddfxf2])
+ #define extenddftf2_libfunc	(libfunc_table[LTI_extenddftf2])
++#define extendbfxf2_libfunc	(libfunc_table[LTI_extendbfxf2])
+ 
+ #define truncdfsf2_libfunc	(libfunc_table[LTI_truncdfsf2])
++#define truncbfsf2_libfunc	(libfunc_table[LTI_truncbfsf2])
+ #define truncxfsf2_libfunc	(libfunc_table[LTI_truncxfsf2])
+ #define trunctfsf2_libfunc	(libfunc_table[LTI_trunctfsf2])
++#define truncbfdf2_libfunc	(libfunc_table[LTI_truncbfdf2])
+ #define truncxfdf2_libfunc	(libfunc_table[LTI_truncxfdf2])
+ #define trunctfdf2_libfunc	(libfunc_table[LTI_trunctfdf2])
++#define truncxfbf2_libfunc	(libfunc_table[LTI_truncxfbf2])
+ 
+ #define abort_libfunc	(libfunc_table[LTI_abort])
+ #define memcpy_libfunc	(libfunc_table[LTI_memcpy])
+@@ -204,6 +236,14 @@
+ #define ledf2_libfunc	(libfunc_table[LTI_ledf2])
+ #define unorddf2_libfunc	(libfunc_table[LTI_unorddf2])
+ 
++#define eqbf2_libfunc	(libfunc_table[LTI_eqbf2])
++#define nebf2_libfunc	(libfunc_table[LTI_nebf2])
++#define gtbf2_libfunc	(libfunc_table[LTI_gtbf2])
++#define gebf2_libfunc	(libfunc_table[LTI_gebf2])
++#define ltbf2_libfunc	(libfunc_table[LTI_ltbf2])
++#define lebf2_libfunc	(libfunc_table[LTI_lebf2])
++#define unordbf2_libfunc	(libfunc_table[LTI_unordbf2])
++
+ #define eqxf2_libfunc	(libfunc_table[LTI_eqxf2])
+ #define nexf2_libfunc	(libfunc_table[LTI_nexf2])
+ #define gtxf2_libfunc	(libfunc_table[LTI_gtxf2])
+@@ -228,6 +268,10 @@
+ #define floatdidf_libfunc	(libfunc_table[LTI_floatdidf])
+ #define floattidf_libfunc	(libfunc_table[LTI_floattidf])
+ 
++#define floatsibf_libfunc	(libfunc_table[LTI_floatsibf])
++#define floatdibf_libfunc	(libfunc_table[LTI_floatdibf])
++#define floattibf_libfunc	(libfunc_table[LTI_floattibf])
++
+ #define floatsixf_libfunc	(libfunc_table[LTI_floatsixf])
+ #define floatdixf_libfunc	(libfunc_table[LTI_floatdixf])
+ #define floattixf_libfunc	(libfunc_table[LTI_floattixf])
+@@ -244,6 +288,10 @@
+ #define fixdfdi_libfunc	(libfunc_table[LTI_fixdfdi])
+ #define fixdfti_libfunc	(libfunc_table[LTI_fixdfti])
+ 
++#define fixbfsi_libfunc	(libfunc_table[LTI_fixbfsi])
++#define fixbfdi_libfunc	(libfunc_table[LTI_fixbfdi])
++#define fixbfti_libfunc	(libfunc_table[LTI_fixbfti])
++
+ #define fixxfsi_libfunc	(libfunc_table[LTI_fixxfsi])
+ #define fixxfdi_libfunc	(libfunc_table[LTI_fixxfdi])
+ #define fixxfti_libfunc	(libfunc_table[LTI_fixxfti])
+@@ -259,6 +307,10 @@
+ #define fixunsdfsi_libfunc	(libfunc_table[LTI_fixunsdfsi])
+ #define fixunsdfdi_libfunc	(libfunc_table[LTI_fixunsdfdi])
+ #define fixunsdfti_libfunc	(libfunc_table[LTI_fixunsdfti])
++
++#define fixunsbfsi_libfunc	(libfunc_table[LTI_fixunsbfsi])
++#define fixunsbfdi_libfunc	(libfunc_table[LTI_fixunsbfdi])
++#define fixunsbfti_libfunc	(libfunc_table[LTI_fixunsbfti])
+ 
+ #define fixunsxfsi_libfunc	(libfunc_table[LTI_fixunsxfsi])
+ #define fixunsxfdi_libfunc	(libfunc_table[LTI_fixunsxfdi])
+diff -Naur gcc-3.3.3.orig/gcc/machmode.def gcc-3.3.3.tigcc8/gcc/machmode.def
+--- gcc-3.3.3.orig/gcc/machmode.def	Tue Sep 17 15:03:40 2002
++++ gcc-3.3.3.tigcc8/gcc/machmode.def	Thu Feb 19 21:20:04 2004
+@@ -93,7 +93,8 @@
+ DEF_MACHMODE (HFmode, "HF", MODE_FLOAT, BITS_PER_UNIT*2, 2, 2, TQFmode, VOIDmode)
+ DEF_MACHMODE (TQFmode, "TQF", MODE_FLOAT, BITS_PER_UNIT*3, 3, 3, SFmode, VOIDmode) /* MIL-STD-1750A */
+ DEF_MACHMODE (SFmode, "SF", MODE_FLOAT, BITS_PER_UNIT*4, 4, 4, DFmode, VOIDmode)
+-DEF_MACHMODE (DFmode, "DF", MODE_FLOAT, BITS_PER_UNIT*8, 8, 8, XFmode, VOIDmode)
++DEF_MACHMODE (DFmode, "DF", MODE_FLOAT, BITS_PER_UNIT*8, 8, 8, BFmode, VOIDmode)
++DEF_MACHMODE (BFmode, "BF", MODE_FLOAT, BITS_PER_UNIT*10, 10, 10, XFmode, VOIDmode) /* SMAP II BCD (inserted for TIGCC) */
+ DEF_MACHMODE (XFmode, "XF", MODE_FLOAT, BITS_PER_UNIT*12, 12, 12, TFmode, VOIDmode) /* IEEE extended */
+ DEF_MACHMODE (TFmode, "TF", MODE_FLOAT, BITS_PER_UNIT*16, 16, 16, VOIDmode, VOIDmode)
+ 
+@@ -101,7 +102,8 @@
+ DEF_MACHMODE (QCmode, "QC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*2, 2, 1, HCmode, QFmode)
+ DEF_MACHMODE (HCmode, "HC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*4, 4, 2, SCmode, HFmode)
+ DEF_MACHMODE (SCmode, "SC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*8, 8, 4, DCmode, SFmode)
+-DEF_MACHMODE (DCmode, "DC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*16, 16, 8, XCmode, DFmode)
++DEF_MACHMODE (DCmode, "DC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*16, 16, 8, BCmode, DFmode)
++DEF_MACHMODE (BCmode, "BC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*20, 20, 10, XCmode, BFmode)
+ DEF_MACHMODE (XCmode, "XC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*24, 24, 12, TCmode, XFmode)
+ DEF_MACHMODE (TCmode, "TC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*32, 32, 16, VOIDmode, TFmode)
+ 
+diff -Naur gcc-3.3.3.orig/gcc/optabs.c gcc-3.3.3.tigcc8/gcc/optabs.c
+--- gcc-3.3.3.orig/gcc/optabs.c	Sat Jul 19 02:25:24 2003
++++ gcc-3.3.3.tigcc8/gcc/optabs.c	Thu Feb 19 21:20:04 2004
+@@ -1833,7 +1833,7 @@
+   /* Look for a wider mode of the same class for which it appears we can do
+      the operation.  */
+ 
+-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
++  if (class == MODE_INT)
+     {
+       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ 	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+@@ -2282,7 +2282,7 @@
+ 
+   /* It can't be done in this mode.  Can we do it in a wider mode?  */
+ 
+-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
++  if (class == MODE_INT)
+     {
+       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ 	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+@@ -2410,7 +2410,7 @@
+ 
+   /* It can't be done in this mode.  Can we open-code it in a wider mode?  */
+ 
+-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
++  if (class == MODE_INT)
+     for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ 	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+       {
+@@ -2551,7 +2551,7 @@
+ 
+   /* It can't be done in this mode.  Can we do it in a wider mode?  */
+ 
+-  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
++  if (class == MODE_INT)
+     {
+       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ 	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+@@ -3875,6 +3875,40 @@
+       default:
+ 	break;
+       }
++  else if (mode == BFmode)
++    switch (comparison)
++      {
++      case EQ:
++	libfunc = eqbf2_libfunc;
++	break;
++
++      case NE:
++	libfunc = nebf2_libfunc;
++	break;
++
++      case GT:
++	libfunc = gtbf2_libfunc;
++	break;
++
++      case GE:
++	libfunc = gebf2_libfunc;
++	break;
++
++      case LT:
++	libfunc = ltbf2_libfunc;
++	break;
++
++      case LE:
++	libfunc = lebf2_libfunc;
++	break;
++
++      case UNORDERED:
++	libfunc = unordbf2_libfunc;
++	break;
++
++      default:
++	break;
++      }
+   else if (mode == XFmode)
+     switch (comparison)
+       {
+@@ -4530,6 +4564,7 @@
+ 	  }
+       }
+ 
++#if 0
+   /* Unsigned integer, and no way to convert directly.
+      Convert as signed, then conditionally adjust the result.  */
+   if (unsignedp)
+@@ -4642,6 +4677,7 @@
+       emit_label (label);
+       goto done;
+     }
++#endif /* 0 */
+ 
+   /* No hardware instruction available; call a library routine to convert from
+      SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
+@@ -4681,6 +4717,17 @@
+ 	  else
+ 	    abort ();
+ 	}
++      else if (GET_MODE (to) == BFmode)
++	{
++	  if (GET_MODE (from) == SImode)
++	    libfcn = floatsibf_libfunc;
++	  else if (GET_MODE (from) == DImode)
++	    libfcn = floatdibf_libfunc;
++	  else if (GET_MODE (from) == TImode)
++	    libfcn = floattibf_libfunc;
++	  else
++	    abort ();
++	}
+       else if (GET_MODE (to) == XFmode)
+ 	{
+ 	  if (GET_MODE (from) == SImode)
+@@ -4792,6 +4839,7 @@
+ 	  }
+       }
+ 
++#if 0
+   /* For an unsigned conversion, there is one more way to do it.
+      If we have a signed conversion, we generate code that compares
+      the real value to the largest representable positive number.  If if
+@@ -4871,6 +4919,7 @@
+ 
+ 	  return;
+ 	}
++#endif /* 0 */
+ 
+   /* We can't do it with an insn, so use a library call.  But first ensure
+      that the mode of TO is at least as wide as SImode, since those are the
+@@ -4904,6 +4953,17 @@
+       else
+ 	abort ();
+     }
++  else if (GET_MODE (from) == BFmode)
++    {
++      if (GET_MODE (to) == SImode)
++	libfcn = unsignedp ? fixunsbfsi_libfunc : fixbfsi_libfunc;
++      else if (GET_MODE (to) == DImode)
++	libfcn = unsignedp ? fixunsbfdi_libfunc : fixbfdi_libfunc;
++      else if (GET_MODE (to) == TImode)
++	libfcn = unsignedp ? fixunsbfti_libfunc : fixbfti_libfunc;
++      else
++	abort ();
++    }
+   else if (GET_MODE (from) == XFmode)
+     {
+       if (GET_MODE (to) == SImode)
+@@ -5327,16 +5387,22 @@
+     = init_one_libfunc ("ffs");
+ 
+   extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
++  extendsfbf2_libfunc = init_one_libfunc ("__extendsfbf2");
+   extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
+   extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
++  extenddfbf2_libfunc = init_one_libfunc ("__extenddfbf2");
+   extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
+   extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
++  extendbfxf2_libfunc = init_one_libfunc ("__extendbfxf2");
+ 
+   truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
++  truncbfsf2_libfunc = init_one_libfunc ("__truncbfsf2");
+   truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
+   trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
++  truncbfdf2_libfunc = init_one_libfunc ("__truncbfdf2");
+   truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
+   trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
++  truncxfbf2_libfunc = init_one_libfunc ("__truncxfbf2");
+ 
+   abort_libfunc = init_one_libfunc ("abort");
+   memcpy_libfunc = init_one_libfunc ("memcpy");
+@@ -5385,6 +5451,14 @@
+   ledf2_libfunc = init_one_libfunc ("__ledf2");
+   unorddf2_libfunc = init_one_libfunc ("__unorddf2");
+ 
++  eqbf2_libfunc = init_one_libfunc ("__eqbf2");
++  nebf2_libfunc = init_one_libfunc ("__nebf2");
++  gtbf2_libfunc = init_one_libfunc ("__gtbf2");
++  gebf2_libfunc = init_one_libfunc ("__gebf2");
++  ltbf2_libfunc = init_one_libfunc ("__ltbf2");
++  lebf2_libfunc = init_one_libfunc ("__lebf2");
++  unordbf2_libfunc = init_one_libfunc ("__unordbf2");
++
+   eqxf2_libfunc = init_one_libfunc ("__eqxf2");
+   nexf2_libfunc = init_one_libfunc ("__nexf2");
+   gtxf2_libfunc = init_one_libfunc ("__gtxf2");
+@@ -5409,6 +5483,10 @@
+   floatdidf_libfunc = init_one_libfunc ("__floatdidf");
+   floattidf_libfunc = init_one_libfunc ("__floattidf");
+ 
++  floatsibf_libfunc = init_one_libfunc ("__floatsibf");
++  floatdibf_libfunc = init_one_libfunc ("__floatdibf");
++  floattibf_libfunc = init_one_libfunc ("__floattibf");
++
+   floatsixf_libfunc = init_one_libfunc ("__floatsixf");
+   floatdixf_libfunc = init_one_libfunc ("__floatdixf");
+   floattixf_libfunc = init_one_libfunc ("__floattixf");
+@@ -5425,6 +5503,10 @@
+   fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
+   fixdfti_libfunc = init_one_libfunc ("__fixdfti");
+ 
++  fixbfsi_libfunc = init_one_libfunc ("__fixbfsi");
++  fixbfdi_libfunc = init_one_libfunc ("__fixbfdi");
++  fixbfti_libfunc = init_one_libfunc ("__fixbfti");
++
+   fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
+   fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
+   fixxfti_libfunc = init_one_libfunc ("__fixxfti");
+@@ -5440,6 +5522,10 @@
+   fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
+   fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
+   fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
++
++  fixunsbfsi_libfunc = init_one_libfunc ("__fixunsbfsi");
++  fixunsbfdi_libfunc = init_one_libfunc ("__fixunsbfdi");
++  fixunsbfti_libfunc = init_one_libfunc ("__fixunsbfti");
+ 
+   fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
+   fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
+diff -Naur gcc-3.3.3.orig/gcc/print-rtl.c gcc-3.3.3.tigcc8/gcc/print-rtl.c
+--- gcc-3.3.3.orig/gcc/print-rtl.c	Sun Jan 26 08:59:38 2003
++++ gcc-3.3.3.tigcc8/gcc/print-rtl.c	Thu Feb 19 21:20:04 2004
+@@ -524,6 +524,9 @@
+ 	{
+ 	  char s[60];
+ 
++	  REAL_VALUE_TO_STRING (*CONST_DOUBLE_REAL_VALUE (in_rtx), s);
++	  fprintf (outfile, " %s", s);
++#if 0
+ 	  real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
+ 			   sizeof (s), 0, 1);
+ 	  fprintf (outfile, " %s", s);
+@@ -531,6 +534,7 @@
+ 	  real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
+ 			       sizeof (s), 0, 1);
+ 	  fprintf (outfile, " [%s]", s);
++#endif /* 0 */
+ 	}
+       break;
+ #endif
+diff -Naur gcc-3.3.3.orig/gcc/print-tree.c gcc-3.3.3.tigcc8/gcc/print-tree.c
+--- gcc-3.3.3.orig/gcc/print-tree.c	Thu Mar  6 23:35:06 2003
++++ gcc-3.3.3.tigcc8/gcc/print-tree.c	Thu Feb 19 21:20:04 2004
+@@ -132,7 +132,7 @@
+       else
+ 	{
+ 	  char string[60];
+-	  real_to_decimal (string, &d, sizeof (string), 0, 1);
++	  REAL_VALUE_TO_STRING (d, string);
+ 	  fprintf (file, " %s", string);
+ 	}
+     }
+@@ -686,7 +686,7 @@
+ 	    else
+ 	      {
+ 		char string[64];
+-		real_to_decimal (string, &d, sizeof (string), 0, 1);
++		REAL_VALUE_TO_STRING (d, string);
+ 		fprintf (file, " %s", string);
+ 	      }
+ 	  }
+diff -Naur gcc-3.3.3.orig/gcc/real.c gcc-3.3.3.tigcc8/gcc/real.c
+--- gcc-3.3.3.orig/gcc/real.c	Thu Nov  6 00:08:56 2003
++++ gcc-3.3.3.tigcc8/gcc/real.c	Thu Feb 19 21:20:04 2004
+@@ -23,11 +23,28 @@
+ 
+ #include "config.h"
+ #include "system.h"
++#include <setjmp.h>
+ #include "tree.h"
+ #include "toplev.h"
+ #include "real.h"
+ #include "tm_p.h"
+ 
++#ifndef NULL_PTR
++#define NULL_PTR ((PTR) 0)
++#endif
++
++/* TIGCC Patch (for SMAP II BCD support): Define this if you want
++   to get info about real arithmetic calculations.  */
++/* #define PRINT_REAL_DEBUG_INFO */
++
++#ifdef PRINT_REAL_DEBUG_INFO
++#define REAL_DEBUG_INFO(info_args...) warning (info_args)
++#define REAL_DEBUG_SPRINTF(sprintf_args...) sprintf (sprintf_args)
++#else
++#define REAL_DEBUG_INFO(info_args...) do {} while (0)
++#define REAL_DEBUG_SPRINTF(sprintf_args...) do {} while (0)
++#endif
++
+ /* The floating point model used internally is not exactly IEEE 754
+    compliant, and close to the description in the ISO C standard,
+    section 5.2.4.2.2 Characteristics of floating types.
+@@ -77,6 +94,7 @@
+  #error "Some constant folding done by hand to avoid shift count warnings"
+ #endif
+ 
++#if 0
+ static void get_zero PARAMS ((REAL_VALUE_TYPE *, int));
+ static void get_canonical_qnan PARAMS ((REAL_VALUE_TYPE *, int));
+ static void get_canonical_snan PARAMS ((REAL_VALUE_TYPE *, int));
+@@ -134,7 +152,9 @@
+ 
+ static void round_for_format PARAMS ((const struct real_format *,
+ 				      REAL_VALUE_TYPE *));
++#endif /* 0 */
+ 
++#if 0
+ /* Initialize R with a positive zero.  */
+ 
+ static inline void
+@@ -1002,6 +1022,625 @@
+       abort ();
+     }
+ }
++#endif /* 0 */
++
++/* Add 1 unit in the last place to a positive SMAP II BCD float. */
++static smap_bcd_float bcdpadd1ulp PARAMS((smap_bcd_float op));
++static smap_bcd_float bcdpadd1ulp(op) smap_bcd_float op;
++{
++  int i;
++  op.mantissa++; /* This will give a digit of 10 in some cases. */
++  for (i=0;i<60;i+=4) { /* for each digit except the first one */
++    int d=(op.mantissa>>i)&15;
++    if (d<10) /* if the digit is <10, we're done */
++      break;
++    op.mantissa += 6ull<<i; /* subtract 10 from the digit, add 1 to the next digit */
++  }
++  /* Now, we should have a carry only in one case: the mantissa was
++     9999999999999999. So now, we have A000000000000000, where A is 10 in a
++     single digit. We can safely truncate the last digit because it is 0 (so
++     there is no risk of double-rounding here). */
++  if (op.mantissa >= 0xA000000000000000ull) { /* if we have a carry */
++    if (op.mantissa != 0xA000000000000000ull) abort(); /* sanity check */
++    op.mantissa = 0x1000000000000000ull; /* A -> 10, drop the last digit */
++    op.exponent++; /* adjust the exponent */
++    if (op.exponent > 0x4000+16383) /* exponent too large, overflow to +infinity */
++      return POSITIVE_INF;
++  }
++  return op;
++}
++
++/* Add 2 positive SMAP II BCD floats. */
++static smap_bcd_float bcdppadd PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdppadd(op0, op1) smap_bcd_float op0, op1;
++{
++  int lastdigit=0;
++
++  if (op0.exponent < op1.exponent) {
++    /* If op0 does not contribute to the result, avoid shift count overflow by
++       returning op1 immediately. */
++    if (op1.exponent-op0.exponent>16) return op1;
++    /* Adjust op0 exponent to fit op1. */
++    op0.mantissa >>= ((op1.exponent-op0.exponent-1)<<2);
++    lastdigit = (op0.mantissa&15); /* save the last digit of op0 */
++    op0.mantissa >>= 4; /* drop the last digit of op0 */
++    op0.exponent = op1.exponent; /* adjust the exponent of op0 */
++  } else if (op1.exponent < op0.exponent) {
++    /* If op1 does not contribute to the result, avoid shift count overflow by
++       returning op0 immediately. */
++    if (op0.exponent-op1.exponent>16) return op0;
++    /* Adjust op1 exponent to fit op0. */
++    op1.mantissa >>= ((op0.exponent-op1.exponent-1)<<2);
++    lastdigit = (op1.mantissa&15); /* save the last digit of op1 */
++    op1.mantissa >>= 4; /* drop the last digit of op1 */
++    op1.exponent = op0.exponent; /* adjust the exponent of op1 */
++  }
++
++  /* Now do the addition in the BCD-coded mantissa. */
++  {
++    int i,d,carry=0;
++    smap_bcd_float result={0,0};result.exponent=op0.exponent;
++    for (i=0;i<64;i+=4) { /* for each digit */
++      d = (op0.mantissa&15)+(op1.mantissa&15)+carry;
++      carry = (d>=10); /* handle carry */
++      if (carry) d -= 10;
++      /* We are done with this digit of the mantissa. */
++      op0.mantissa >>= 4;
++      op1.mantissa >>= 4;
++      /* Store it into the resulting mantissa. */
++      result.mantissa += ((unsigned long long)d)<<i;
++    }
++    if (carry) { /* The mantissa overflowed, so we need to adjust the exponent. */
++      lastdigit = (result.mantissa&15); /* save the last digit of result,
++                                           dropping the previously saved last
++                                           digit */
++      result.mantissa >>= 4; /* drop the last digit of result */
++      result.exponent++; /* adjust the exponent of result */
++      if (result.exponent > 0x4000+16383) /* exponent too large, overflow to */
++        return POSITIVE_INF;              /* +infinity */
++      /* prepend the first digit */
++      result.mantissa += ((unsigned long long)carry)<<60;
++    }
++    if (lastdigit>=5) /* now do the correct rounding */
++      result = bcdpadd1ulp(result);
++    return result;
++  }
++}
++
++/* Subtract 2 positive SMAP II BCD floats. */
++static smap_bcd_float bcdppsub PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdppsub(op0, op1) smap_bcd_float op0, op1;
++{
++  unsigned long long lastdigits=0;
++
++  if (REAL_VALUES_LESS(op0,op1)) /* if op0<op1, subtract the other way round */
++    return REAL_VALUE_NEGATE(bcdppsub(op1,op0));
++  else if (REAL_VALUES_IDENTICAL(op0,op1)) /* if op0=op1, return unsigned 0 */
++    return UNSIGNED_ZERO;
++
++  /* Now, we can assume op0>op1. */
++  if (op1.exponent < op0.exponent) {
++    /* If op1 does not contribute to the result, avoid shift count overflow by
++       returning op0 immediately. */
++    if (op0.exponent-op1.exponent>16) return op0;
++    /* Adjust op1 exponent to fit op0.
++       Save all dropped digits, so we can round correctly. */
++    lastdigits = op1.mantissa << (64-((op0.exponent-op1.exponent)<<2));
++    if (op0.exponent-op1.exponent==16)
++      op1.mantissa = 0; /* special-cased because shifts by 64 aren't allowed */
++    else
++      op1.mantissa >>= ((op0.exponent-op1.exponent)<<2);
++    op1.exponent = op0.exponent; /* adjust the exponent of op1 */
++  }
++
++  /* Now do the subtraction in the BCD-coded mantissa. */
++  {
++    int i,d,carry=0;
++    smap_bcd_float result={0,0};result.exponent=op0.exponent;
++    for (i=0;i<64;i+=4) { /* for each digit */
++      d = (op0.mantissa&15)-((op1.mantissa&15)+carry);
++      carry = (d<0); /* handle carry */
++      if (carry) d += 10;
++      /* We are done with this digit of the mantissa. */
++      op0.mantissa >>= 4;
++      op1.mantissa >>= 4;
++      /* Store it into the resulting mantissa. */
++      result.mantissa += ((unsigned long long)d)<<i;
++    }
++    if (carry) abort(); /* Carry should be 0 here! */
++    /* Normalize and return the result (which is always positive here, since we
++       assumed op1>op0). Handle rounding and extra digits during normalization.
++       */
++    while ((result.mantissa<0x1000000000000000ull)
++           || ((result.mantissa==0x1000000000000000ull)
++              && ((lastdigits>0x5000000000000000ull)
++                 || ((lastdigits>0x500000000000000ull)
++                     && (result.exponent>0x4000-16383))))) {
++    /* while mantissa<1 */
++      int c = (result.mantissa==0x1000000000000000ull); /* used by the sanity
++                                                           check below */
++      result.exponent--; /* decrease exponent by 1 */
++      if (result.exponent<0x4000-16383) /* exponent too small, underflow to +0 */
++        return POSITIVE_ZERO;
++      result.mantissa <<= 4; /* left-shift mantissa */
++      carry = !!(lastdigits>>60);
++      result.mantissa -= (lastdigits>>60)+(carry*6); /* Subtract extra digit. If
++        there is a carry, add 10 to the digit, subtract 1 from the next digit.
++        This can give digits of 15 in some cases. */
++      for (i=4;i<64;i+=4) { /* for each digit except the last one */
++        int d=(result.mantissa>>i)&15;
++        if (d<10) /* if the digit is <10, we're done */
++          break;
++        result.mantissa -= 6ull<<i; /* add 10 to the digit, subtract 1 from the
++                                       next digit */
++        /* There should be no carry in the first digit except if the mantissa
++           was exactly 1. */
++        if (!c && result.mantissa>=0xA000000000000000ull) abort();
++      }
++      lastdigits <<= 4; /* We handled an extra digit. */
++    }
++    /* Now do the rounding. */
++    if (lastdigits>0x5000000000000000ull) {
++      int c = !result.mantissa; /* used by the sanity check below */
++      /* This corner case should have been handled above. */
++      if (result.mantissa==0x1000000000000000ull) abort();
++      result.mantissa--; /* Subtract 1. This can give digits of 15 in some cases. */
++      for (i=0;i<64;i+=4) { /* for each digit */
++        int d=(result.mantissa>>i)&15;
++        if (d<10) /* if the digit is <10, we're done */
++          break;
++        result.mantissa -= 6ull<<i; /* add 10 to the digit, subtract 1 from the
++                                       next digit */
++        /* There should be no carry in the first digit except if the mantissa was
++           0 (which actually means 10^16 here). */
++        if (!c && result.mantissa>=0xA000000000000000ull) abort();
++      }
++    }
++    return result;
++  }
++}
++
++/* Add 2 SMAP II BCD floats. */
++static smap_bcd_float bcdadd PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdadd(op0, op1) smap_bcd_float op0, op1;
++{
++  if (REAL_VALUE_ISNAN(op0) || REAL_VALUE_ISNAN(op1)) /* keep NAN */
++    return NAN;
++  else if (REAL_VALUE_ISINF(op0) && REAL_VALUE_ISINF(op1)) { /* both operands
++                                                                are infinity */
++    if (REAL_VALUES_IDENTICAL(op0,op1)) /* both positive, both negative or both
++                                           unsigned */
++      return op0;
++    else /* differing signs yield unsigned infinity */
++      return UNSIGNED_INF;
++  } else if (REAL_VALUE_ISINF(op0)) /* op0=inf, so op0+op1=inf+op1=inf=op0 */
++    return op0;
++  else if (REAL_VALUE_ISINF(op1)) /* op1=inf, so op0+op1=op0+inf=inf=op1 */
++    return op1;
++  else if (REAL_VALUE_ISZERO(op0) && REAL_VALUE_ISZERO(op1)) { /* both operands
++                                                                  are 0 */
++    if (REAL_VALUES_IDENTICAL(op0,op1)) /* both positive, both negative or both
++                                           unsigned */
++      return op0;
++    else /* differing signs yield unsigned zero */
++      return UNSIGNED_ZERO;
++  } else if (REAL_VALUE_ISZERO(op0)) /* op0=0, so op0+op1=0+op1=op1 */
++    return op1;
++  else if (REAL_VALUE_ISZERO(op1)) /* op1=0, so op0+op1=op0+0=op0 */
++    return op0;
++  else if (REAL_VALUE_ISPOSITIVE(op0) && REAL_VALUE_ISPOSITIVE(op1))
++    return bcdppadd(op0,op1);
++  else if (REAL_VALUE_ISPOSITIVE(op0)) /* and op1 negative */
++    return bcdppsub(op0,REAL_VALUE_NEGATE(op1));
++  else if (REAL_VALUE_ISPOSITIVE(op1)) /* and op0 negative */
++    return bcdppsub(op1,REAL_VALUE_NEGATE(op0));
++  else /* both negative */
++    return REAL_VALUE_NEGATE(bcdppadd(REAL_VALUE_NEGATE(op0),
++                                      REAL_VALUE_NEGATE(op1)));
++}
++
++/* Subtract 2 SMAP II BCD floats. */
++static smap_bcd_float bcdsub PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdsub(op0, op1) smap_bcd_float op0, op1;
++{
++  return bcdadd(op0,REAL_VALUE_NEGATE(op1));
++}
++
++/* Multiply 2 positive SMAP II BCD floats. */
++static smap_bcd_float bcdppmul PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdppmul(op0, op1) smap_bcd_float op0, op1;
++{
++  /* Compute the result in 2 binary parts. The upper 16 decimal digits and the
++     lower ones. */
++  unsigned long long resulth=0, resultl=0;
++  int i,j,k,d0,d1,d32,exponent;
++  unsigned long long factor=1ull;
++  for (i=0;i<64;i+=4,factor*=10ull) { /* for each result digit <16 */
++    for (j=0;j<64;j+=4) { /* for each digit of op0 */
++      k = i-j; /* corresponding op1 digit */
++      if (k<0 || k>=64) continue; /* digit out of range */
++      d0 = (op0.mantissa>>j)&15; /* jth digit of op0 */
++      d1 = (op1.mantissa>>k)&15; /* kth digit of op0 */
++      resultl += (unsigned long long)(d0*d1)*factor;
++      while (resultl>=10000000000000000ull/*10^16*/) { /* carry into resulth */
++        resultl -= 10000000000000000ull/*10^16*/;
++        resulth++;
++      }
++    }
++  }
++  for (factor=1ull;i<128;i+=4,factor*=10ull) { /* for each result digit >=16 */
++    for (j=0;j<64;j+=4) { /* for each digit of op0 */
++      k = i-j; /* corresponding op1 digit */
++      if (k<0 || k>=64) continue; /* digit out of range */
++      d0 = (op0.mantissa>>j)&15; /* jth digit of op0 */
++      d1 = (op1.mantissa>>k)&15; /* kth digit of op0 */
++      resulth += (unsigned long long)(d0*d1)*factor;
++    }
++  }
++
++  /* resultl should always be <10^16 */
++  if (resultl>=10000000000000000ull) abort();
++
++  /* Because of normalization, the result has either 31 or 32 digits. */
++  d32 = (resulth>=1000000000000000ull/*10^15*/
++         || (resulth==999999999999999ull/*10^15-1*/
++             && resultl>=9500000000000000ull/*9.5*10^15*/));
++  if (!d32) { /* if we have only 15 digits in resulth, take one from resultl */
++    resulth = resulth*10ull+resultl/1000000000000000ull/*10^15*/;
++    resultl = (resultl%1000000000000000ull/*10^15*/)*10ull;
++  }
++  if (resultl>=5000000000000000ull/*5*10^15*/) /* round resultl into resulth */
++    resulth++;
++
++  /* Now compute the exponent. */
++  exponent=op0.exponent+op1.exponent-0x4000+d32;
++  if (exponent>0x4000+16383) /* exponent too large, overflow to +infinity */
++    return POSITIVE_INF;
++  if (exponent<0x4000-16383) /* exponent too small, underflow to +0 */
++    return POSITIVE_ZERO;
++
++  /* Now convert resulth into a BCD mantissa. */
++  {
++    unsigned long long d;
++    smap_bcd_float result={0,0};result.exponent=exponent;
++    for (i=0;i<64;i+=4) { /* for each digit */
++      d = resulth%10ull; /* Extract the digit. */
++      resulth /= 10ull; /* We are done with this digit of the mantissa. */
++      result.mantissa += d<<i; /* Store it into the resulting mantissa. */
++    }
++    return result;
++  }
++}
++
++/* Multiply 2 SMAP II BCD floats. */
++static smap_bcd_float bcdmul PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdmul(op0, op1) smap_bcd_float op0, op1;
++{
++  if (REAL_VALUE_ISNAN(op0) || REAL_VALUE_ISNAN(op1)
++      || (REAL_VALUE_ISINF(op0) && REAL_VALUE_ISZERO(op1))
++      || (REAL_VALUE_ISZERO(op0) && REAL_VALUE_ISINF(op1))) /* keep NAN,
++                                                               0*inf=NAN */
++    return NAN;
++  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_INF)
++           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_INF)) /* unsigned inf * non-0 =
++                                                          unsigned inf */
++    return UNSIGNED_INF;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +inf * +inf = +inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -inf * -inf = +inf */
++    return POSITIVE_INF;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +inf * -inf = -inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -inf * +inf = -inf */
++    return NEGATIVE_INF;
++  /* Now we can assume that at least 1 value is finite, and that we don't have
++     an unsigned infinity, a NAN or an inf*0 indeterminate form. */
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUE_ISPOSITIVE(op1)) /* +inf * +finite = +inf */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +finite * +inf = +inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUE_ISNEGATIVE(op1)) /* -inf * -finite = +inf */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -finite * -inf = +inf */
++    return POSITIVE_INF;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUE_ISNEGATIVE(op1)) /* +inf * -finite = -inf */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +finite * -inf = -inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUE_ISPOSITIVE(op1)) /* -inf * +finite = -inf */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -finite * +inf = -inf */
++    return NEGATIVE_INF;
++  /* Now we can assume that both values are finite. */
++  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_ZERO)
++           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_ZERO)) /* unsigned 0 * finite =
++                                                           unsigned 0 */
++    return UNSIGNED_ZERO;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +0 * +0 = +0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -0 * -0 = +0 */
++    return POSITIVE_ZERO;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +0 * -0 = -0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -0 * +0 = -0 */
++    return NEGATIVE_ZERO;
++  /* Now we can assume that both values are finite, at least 1 value is non-0,
++     and that we don't have an unsigned 0. */
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUE_ISPOSITIVE(op1)) /* +0 * +finite = +0 */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +finite * +0 = +0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUE_ISNEGATIVE(op1)) /* -0 * -finite = +0 */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -finite * -0 = +0 */
++    return POSITIVE_ZERO;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUE_ISNEGATIVE(op1)) /* +0 * -finite = -0 */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +finite * -0 = -0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUE_ISPOSITIVE(op1)) /* -0 * +finite = -0 */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -finite * +0 = -0 */
++    return NEGATIVE_ZERO;
++  /* Now we can assume that both values are finite and non-0. */
++  else if (REAL_VALUE_ISPOSITIVE(op0) && REAL_VALUE_ISPOSITIVE(op1))
++    return bcdppmul(op0,op1);
++  else if (REAL_VALUE_ISPOSITIVE(op0)) /* and op1 negative */
++    return REAL_VALUE_NEGATE(bcdppmul(op0,REAL_VALUE_NEGATE(op1)));
++  else if (REAL_VALUE_ISPOSITIVE(op1)) /* and op0 negative */
++    return REAL_VALUE_NEGATE(bcdppmul(REAL_VALUE_NEGATE(op0),op1));
++  else /* both negative */
++    return bcdppmul(REAL_VALUE_NEGATE(op0),REAL_VALUE_NEGATE(op1));
++}
++
++/* Divide 2 positive SMAP II BCD floats. Indicate if the computed result was exact. */
++static smap_bcd_float bcdppdiv PARAMS((smap_bcd_float op0, smap_bcd_float op1, int *exactresult));
++static smap_bcd_float bcdppdiv(op0, op1, exactresult) smap_bcd_float op0, op1; int *exactresult;
++{
++  /* The dividend is represented multiplied by 10^16, and in 2 binary parts. The
++     upper 64 bits and the lower ones. The divisor is represented in binary, in
++     2 parts to allow shifting. Compute the result mantissa in binary. */
++  unsigned long long dividendh, dividendl=0, divisorh, divisorl=0, resultm=0;
++  int i,d17,exponent;
++  unsigned long long factor=1ull;
++  /* Convert the mantissa of op0 to binary. */
++  for (i=0;i<64;i+=4,factor*=10ull) /* for each digit of op0 */
++    dividendl += (unsigned long long)((op0.mantissa>>i)&15)*factor;
++  /* Multiply the dividend with 10^16. */
++  dividendh = dividendl>>48; /* multiply first 16 bits with 2^16 */
++  dividendh *= 152587890625ull; /* and with 5^16 */
++  dividendl &= 0xFFFFFFFFFFFFull; /* remove them from dividendl */
++  dividendl *= 15625ull; /* multiply the remaining 48 bits with 5^6
++                            we still have to multiply them by 2^16*5^10 */
++  dividendh += (dividendl>>48)*9765625ull; /* multiply first 16 bits with 2^16*5^10 */
++  dividendl &= 0xFFFFFFFFFFFFull; /* remove them from dividendl */
++  dividendl *= 15625ull; /* multiply the remaining 48 bits with 5^6
++                            we still have to multiply them by 2^16*5^4 */
++  dividendh += (dividendl>>48)*625ull; /* multiply first 16 bits with 2^16*5^4 */
++  dividendl &= 0xFFFFFFFFFFFFull; /* remove them from dividendl */
++  dividendl *= 625ull; /* multiply the remaining 48 bits with 5^4
++                          we still have to multiply them by 2^16 */
++  dividendh += dividendl>>48; /* multiply first 16 bits with 2^16 */
++  dividendl <<= 16; /* multiply the remaining 48 bits with 2^16 */
++  /* Convert the mantissa of op1 to binary. */
++  for (i=0,factor=1ull;i<64;i+=4,factor*=10ull) /* for each digit of op1 */
++    divisorl += (unsigned long long)((op1.mantissa>>i)&15)*factor;
++  /* Multiply the divisor with 2^56. We know that, due to normalization, the
++     result is always <10^17, which is smaller than 2^57, so we don't have to go
++     through the full 128-bit division. */
++  divisorh = divisorl>>(64-56);
++  divisorl <<= 56;
++  /* Now do the 128-bit division. */
++  for (i=56;i>=0;i--) {
++    /* Shift the result to the left. */
++    resultm <<= 1;
++    /* Check if the divisor fits into the dividend. */
++    if (divisorh<dividendh || (divisorh==dividendh && divisorl<=dividendl)) {
++      /* Add 1 to the result. */
++      resultm++;
++      /* Subtract the divisor from the dividend. */
++      if (dividendl<divisorl) /* handle carry, use unsigned wraparound overflow */
++        dividendh--;
++      dividendl -= divisorl; /* now do the subtraction */
++      dividendh -= divisorh;
++    }
++    if (i) {
++      /* Shift the divisor to the right. */
++      divisorl = ((divisorh&1)<<63)+(divisorl>>1);
++      divisorh >>= 1;
++    }
++  }
++  /* dividendl now contains the remainder. It is always smaller than the
++     divisor, so it always fits into 64 bits. divisorl now contains the original
++     divisor. */
++
++  if (exactresult)
++    *exactresult = !dividendl; /* if there is a remainder, the result sure is
++                                  not exact, otherwise, let's assume it is for
++                                  a moment */
++
++  /* Because of normalization, the result has either 16 or 17 digits. */
++  d17 = (resultm>=10000000000000000ull/*10^16*/
++         || (resultm==9999999999999999ull/*10^16-1*/
++             && (dividendl<<1)>=divisorl) /* 2r>=d <=> r>=d/2 */);
++  if (d17) { /* if we have 17 digits in the result, drop one */
++    if (exactresult && (resultm%10ull)) /* if we are about to drop a non-0
++                                           digit, the result is not exact
++                                           anymore */
++      *exactresult = 0;
++    resultm = (resultm+5ull)/10ull; /* add 5 for correct rounding */
++  } else {
++    if ((dividendl<<1)>=divisorl /* r>=d/2 */) /* round remainder into result */
++      resultm++;
++  }
++
++  /* Now compute the exponent. */
++  exponent=op0.exponent-op1.exponent+0x4000-(!d17);
++  if (exactresult && (exponent>0x4000+16383 || exponent<0x4000-16383))
++    /* if we overflowed, the result is not exact anymore */
++    *exactresult = 0;
++  if (exponent>0x4000+16383) /* exponent too large, overflow to +infinity */
++    return POSITIVE_INF;
++  if (exponent<0x4000-16383) /* exponent too small, underflow to +0 */
++    return POSITIVE_ZERO;
++
++  /* Now convert resulth into a BCD mantissa. */
++  {
++    unsigned long long d;
++    smap_bcd_float result={0,0};result.exponent=exponent;
++    for (i=0;i<64;i+=4) { /* for each digit */
++      d = resultm%10ull; /* Extract the digit. */
++      resultm /= 10ull; /* We are done with this digit of the mantissa. */
++      result.mantissa += d<<i; /* Store it into the resulting mantissa. */
++    }
++    return result;
++  }
++}
++
++/* Divide 2 SMAP II BCD floats. Indicate if the computed result was exact. */
++static smap_bcd_float bcddiv PARAMS((smap_bcd_float op0, smap_bcd_float op1, int *exactresult));
++static smap_bcd_float bcddiv(op0, op1, exactresult) smap_bcd_float op0, op1; int *exactresult;
++{
++  if (exactresult) *exactresult=1; /* special cases are all exact */
++  if (REAL_VALUE_ISNAN(op0) || REAL_VALUE_ISNAN(op1)
++      || (REAL_VALUE_ISINF(op0) && REAL_VALUE_ISINF(op1))
++      || (REAL_VALUE_ISZERO(op0) && REAL_VALUE_ISZERO(op1))) /* keep NAN,
++                                                                0/0=inf/inf=NAN */
++    return NAN;
++  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_INF)
++           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_ZERO)) /* unsigned inf / finite
++                                          = non-0 / unsigned 0 = unsigned inf */
++    return UNSIGNED_INF;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +inf / +0 = +inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -inf / -0 = +inf */
++    return POSITIVE_INF;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +inf / -0 = -inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -inf / +0 = -inf */
++    return NEGATIVE_INF;
++  /* Now we can assume that at least 1 of op0 and 1/op1 is finite, and that we
++     don't have op0 = unsigned inf, op1 = unsigned 0, a NAN or an inf/inf or 0/0
++     indeterminate form. */
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUE_ISPOSITIVE(op1)) /* +inf / +non-0 = +inf */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO)) /* +finite / +0 = +inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUE_ISNEGATIVE(op1)) /* -inf / -non-0 = +inf */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO))) /* -finite / -0 = +inf */
++    return POSITIVE_INF;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++            && REAL_VALUE_ISNEGATIVE(op1)) /* +inf / -non-0 = -inf */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_ZERO)) /* +finite / -0 = -inf */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++               && REAL_VALUE_ISPOSITIVE(op1)) /* -inf / +non-0 = -inf */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_ZERO))) /* -finite / +0 = -inf */
++    return NEGATIVE_INF;
++  /* Now we can assume that both of op0 and 1/op1 are finite. */
++  else if (REAL_VALUES_IDENTICAL(op0,UNSIGNED_ZERO)
++           || REAL_VALUES_IDENTICAL(op1,UNSIGNED_INF)) /* unsigned 0 / non-0 =
++                                           finite / unsigned inf = unsigned 0 */
++    return UNSIGNED_ZERO;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +0 / +inf = +0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -0 / -inf = +0 */
++    return POSITIVE_ZERO;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +0 / -inf = -0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -0 / +inf = -0 */
++    return NEGATIVE_ZERO;
++  /* Now we can assume that both of op0 and 1/op1 are finite, at least 1 of them
++     is non-0, and that neither of them is an unsigned 0. */
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUE_ISPOSITIVE(op1)) /* +0 / +non-0 = +0 */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* +finite / +inf = +0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUE_ISNEGATIVE(op1)) /* -0 / -non-0 = +0 */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF))) /* -finite / -inf = +0 */
++    return POSITIVE_ZERO;
++  else if ((REAL_VALUES_IDENTICAL(op0,POSITIVE_ZERO)
++            && REAL_VALUE_ISNEGATIVE(op1)) /* +0 / -non-0 = -0 */
++           || (REAL_VALUE_ISPOSITIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* +finite / -inf = -0 */
++           || (REAL_VALUES_IDENTICAL(op0,NEGATIVE_ZERO)
++               && REAL_VALUE_ISPOSITIVE(op1)) /* -0 / +non-0 = -0 */
++           || (REAL_VALUE_ISNEGATIVE(op0)
++               && REAL_VALUES_IDENTICAL(op1,POSITIVE_INF))) /* -finite / +inf = -0 */
++    return NEGATIVE_ZERO;
++  /* Now we can assume that both values are finite and non-0. */
++  else if (REAL_VALUE_ISPOSITIVE(op0) && REAL_VALUE_ISPOSITIVE(op1))
++    return bcdppdiv(op0,op1,exactresult);
++  else if (REAL_VALUE_ISPOSITIVE(op0)) /* and op1 negative */
++    return REAL_VALUE_NEGATE(bcdppdiv(op0,REAL_VALUE_NEGATE(op1),exactresult));
++  else if (REAL_VALUE_ISPOSITIVE(op1)) /* and op0 negative */
++    return REAL_VALUE_NEGATE(bcdppdiv(REAL_VALUE_NEGATE(op0),op1,exactresult));
++  else /* both negative */
++    return bcdppdiv(REAL_VALUE_NEGATE(op0),REAL_VALUE_NEGATE(op1),exactresult);
++}
++
++/* Compute min of 2 SMAP II BCD floats. */
++static smap_bcd_float bcdmin PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdmin(op0, op1) smap_bcd_float op0, op1;
++{
++  if (REAL_VALUE_ISNANUINF(op0) || REAL_VALUE_ISNANUINF(op1)) /* keep NAN,
++                    UNSIGNED_INF is neither smaller nor larger than the other */
++    return NAN;
++  else if (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)
++           || REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* keep -infinity */
++    return NEGATIVE_INF;
++  else if (REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)) /* all numbers are smaller
++                                                       than +infinity */
++    return op1;
++  else if (REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* all numbers are smaller
++                                                       than +infinity */
++    return op0;
++  /* Now, we can assume that all values are finite. */
++  else if (REAL_VALUES_LESS(op0,op1)) /* if op0<op1, return op0 */
++    return op0;
++  else /* if op0>=op1, return op1 */
++    return op1;
++}
++
++/* Compute max of 2 SMAP II BCD floats. */
++static smap_bcd_float bcdmax PARAMS((smap_bcd_float op0, smap_bcd_float op1));
++static smap_bcd_float bcdmax(op0, op1) smap_bcd_float op0, op1;
++{
++  if (REAL_VALUE_ISNANUINF(op0) || REAL_VALUE_ISNANUINF(op1)) /* keep NAN,
++                    UNSIGNED_INF is neither smaller nor larger than the other */
++    return NAN;
++  else if (REAL_VALUES_IDENTICAL(op0,POSITIVE_INF)
++           || REAL_VALUES_IDENTICAL(op1,POSITIVE_INF)) /* keep +infinity */
++    return POSITIVE_INF;
++  else if (REAL_VALUES_IDENTICAL(op0,NEGATIVE_INF)) /* all numbers are smaller
++                                                       than -infinity */
++    return op1;
++  else if (REAL_VALUES_IDENTICAL(op1,NEGATIVE_INF)) /* all numbers are smaller
++                                                       than -infinity */
++    return op0;
++  /* Now, we can assume that all values are finite. */
++  else if (REAL_VALUES_LESS(op0,op1)) /* if op0<op1, return op1 */
++    return op1;
++  else /* if op0>=op1, return op0 */
++    return op0;
++}
+ 
+ /* Perform the binary or unary operation described by CODE.
+    For a unary operation, leave OP1 NULL.  */
+@@ -1012,6 +1651,37 @@
+      int icode;
+      const REAL_VALUE_TYPE *op0, *op1;
+ {
++  switch (icode)
++    {
++    case PLUS_EXPR:
++      *r = bcdadd (*op0, *op1);
++      return;
++
++    case MINUS_EXPR:
++      *r = bcdsub (*op0, *op1);
++      return;
++
++    case MULT_EXPR:
++      *r = bcdmul (*op0, *op1);
++      return;
++
++    case RDIV_EXPR:
++      *r = bcddiv (*op0, *op1, NULL);
++      return;
++
++    case MIN_EXPR:
++      *r = bcdmin (*op0, *op1);
++      return;
++
++    case MAX_EXPR:
++      *r = bcdmax (*op0, *op1);
++      return;
++
++    default:
++      abort ();
++    }
++
++#if 0
+   enum tree_code code = icode;
+ 
+   switch (code)
+@@ -1067,6 +1737,7 @@
+     default:
+       abort ();
+     }
++#endif /* 0 */
+ }
+ 
+ /* Legacy.  Similar, but return the result directly.  */
+@@ -1081,6 +1752,7 @@
+   return r;
+ }
+ 
++#if 0
+ bool
+ real_compare (icode, op0, op1)
+      int icode;
+@@ -1244,6 +1916,7 @@
+ 
+   return true;
+ }
++#endif /* 0 */
+ 
+ /* Try to change R into its exact multiplicative inverse in machine
+    mode MODE.  Return true if successful.  */
+@@ -1253,6 +1926,13 @@
+      enum machine_mode mode;
+      REAL_VALUE_TYPE *r;
+ {
++  int exactresult=0;
++  smap_bcd_float one={0x4000,0x1000000000000000ull}, invr;
++
++  invr = bcddiv(one,*r,&exactresult);
++  if (exactresult) *r=invr;
++  return exactresult;
++#if 0
+   const REAL_VALUE_TYPE *one = real_digit (1);
+   REAL_VALUE_TYPE u;
+   int i;
+@@ -1282,8 +1962,10 @@
+ 
+   *r = u;
+   return true;
++#endif /* 0 */
+ }
+ 
++#if 0
+ /* Render R as an integer.  */
+ 
+ HOST_WIDE_INT
+@@ -1407,7 +2089,29 @@
+   *plow = low;
+   *phigh = high;
+ }
++#endif /* 0 */
++
++/* REAL_VALUE_TO_INT macro.  */
++
++void
++ereal_to_int (low, high, rr)
++     HOST_WIDE_INT *low, *high;
++     REAL_VALUE_TYPE rr;
++{
++  char s[100];
++  REAL_DEBUG_INFO ("ereal_to_int rr: %x:%lx-%lx", rr.exponent, (unsigned long) (rr.mantissa >> 32), (unsigned long) (rr.mantissa));
++  REAL_VALUE_TO_STRING (rr, s);
++  REAL_DEBUG_INFO ("ereal_to_int s: %s", s);
++  *low = (HOST_WIDE_INT) (atof (s));
++  if (*low < 0)
++    *high = -1;
++  else
++    *high = 0;
++  REAL_DEBUG_INFO ("ereal_to_int high: %ld", (long) *high);
++  REAL_DEBUG_INFO ("ereal_to_int low: %ld", (long) *low);
++}
+ 
++#if 0
+ /* A subroutine of real_to_decimal.  Compute the quotient and remainder
+    of NUM / DEN.  Return the quotient and place the remainder in NUM.
+    It is expected that NUM / DEN are close enough that the quotient is
+@@ -2045,7 +2749,39 @@
+   if (mode != VOIDmode)
+     real_convert (r, mode, r);
+ }
++#endif /* 0 */
++
++/* REAL_VALUE_FROM_INT macro.  */
++
++void
++ereal_from_int (d, i, j, mode)
++     REAL_VALUE_TYPE *d;
++     HOST_WIDE_INT i, j;
++     enum machine_mode mode;
++{
++  char s[20];
++  sprintf (s, "%ld", (long) i);
++  REAL_DEBUG_INFO ("ereal_from_int s: %s", s);
++  *d = REAL_VALUE_ATOF (s, mode);
++  REAL_DEBUG_INFO ("ereal_from_int d: %x:%lx-%lx", d->exponent, (unsigned long) (d->mantissa >> 32), (unsigned long) (d->mantissa));
++}
+ 
++/* REAL_VALUE_FROM_UNSIGNED_INT macro.  */
++
++void
++ereal_from_uint (d, i, j, mode)
++     REAL_VALUE_TYPE *d;
++     unsigned HOST_WIDE_INT i, j;
++     enum machine_mode mode;
++{
++  char s[20];
++  sprintf (s, "%lu", (unsigned long) i);
++  REAL_DEBUG_INFO ("ereal_from_uint s: %s", s);
++  *d = REAL_VALUE_ATOF (s, mode);
++  REAL_DEBUG_INFO ("ereal_from_uint d: %x:%lx-%lx", d->exponent, (unsigned long) (d->mantissa >> 32), (unsigned long) (d->mantissa));
++}
++
++#if 0
+ /* Returns 10**2**N.  */
+ 
+ static const REAL_VALUE_TYPE *
+@@ -2556,6 +3292,7 @@
+ 
+   return fmt->p * fmt->log2_b;
+ }
++#endif /* 0 */
+ 
+ /* Return a hash value for the given real value.  */
+ /* ??? The "unsigned int" return value is intended to be hashval_t,
+@@ -2565,6 +3302,12 @@
+ real_hash (r)
+      const REAL_VALUE_TYPE *r;
+ {
++  /* (TIGCC) Very naive hash for lack of something better. -- Kevin Kofler */
++  unsigned int h=r->exponent;
++  return h+(unsigned int)(r->mantissa >>
++                          ((sizeof(unsigned long long)-sizeof(unsigned int))*8));
++
++#if 0
+   unsigned int h;
+   size_t i;
+ 
+@@ -2596,8 +3339,10 @@
+     }
+ 
+   return h;
++#endif /* 0 */
+ }
+ 
++#if 0
+ /* IEEE single-precision format.  */
+ 
+ static void encode_ieee_single PARAMS ((const struct real_format *fmt,
+@@ -4414,3 +5159,5 @@
+   NULL,				/* XFmode */
+   &ieee_quad_format		/* TFmode */
+ };
++#endif /* 0 */
++
+diff -Naur gcc-3.3.3.orig/gcc/real.h gcc-3.3.3.tigcc8/gcc/real.h
+--- gcc-3.3.3.orig/gcc/real.h	Wed Jul  2 03:28:44 2003
++++ gcc-3.3.3.tigcc8/gcc/real.h	Thu Feb 19 21:20:04 2004
+@@ -22,6 +22,22 @@
+ #ifndef GCC_REAL_H
+ #define GCC_REAL_H
+ 
++/* (TIGCC) smapbcd.h need this, but gengtype needs it to be in this file. */
++/* (TIGCC) Hack to make gengtype shut up while still packing the structure. */
++#define exponent exponent __attribute__((packed))
++#define mantissa mantissa __attribute__((packed))
++__attribute__ ((packed))
++struct real_value GTY(())
++{
++	unsigned short exponent;
++	unsigned long long mantissa;
++};
++#undef exponent
++#undef mantissa
++
++#include <smapbcd.h>
++#define SMAP_BCD_FLOAT_FORMAT 5
++
+ #include "machmode.h"
+ 
+ /* An expanded form of the represented number.  */
+@@ -40,6 +56,7 @@
+ #define SIGSZ			(SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
+ #define SIG_MSB			((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
+ 
++/*
+ struct real_value GTY(())
+ {
+   ENUM_BITFIELD (real_value_class) class : 2;
+@@ -47,7 +64,9 @@
+   signed int exp : EXP_BITS;
+   unsigned long sig[SIGSZ];
+ };
++*/
+ 
++#if 0
+ /* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it
+    needs to be a macro.  We do need to continue to have a structure tag
+    so that other headers can forward declare it.  */
+@@ -65,6 +84,9 @@
+ /* Verify the guess.  */
+ extern char test_real_width
+   [sizeof(REAL_VALUE_TYPE) <= REAL_WIDTH*sizeof(HOST_WIDE_INT) ? 1 : -1];
++#endif /* 0 */
++
++#define REAL_WIDTH (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
+ 
+ /* Calculate the format for CONST_DOUBLE.  We need as many slots as
+    are necessary to overlay a REAL_VALUE_TYPE on them.  This could be
+@@ -100,6 +122,7 @@
+ #endif
+ 
+ 
++#if 0
+ /* Describes the properties of the specific target format in use.  */
+ struct real_format
+ {
+@@ -136,6 +159,7 @@
+ /* The target format used for each floating floating point mode.
+    Indexed by MODE - QFmode.  */
+ extern const struct real_format *real_format_for_mode[TFmode - QFmode + 1];
++#endif /* 0 */
+ 
+ 
+ /* Declare functions in real.c.  */
+@@ -145,6 +169,7 @@
+ 					 const REAL_VALUE_TYPE *,
+ 					 const REAL_VALUE_TYPE *));
+ 
++#if 0
+ /* Compare reals by tree_code.  */
+ extern bool real_compare	PARAMS ((int, const REAL_VALUE_TYPE *,
+ 					 const REAL_VALUE_TYPE *));
+@@ -212,9 +237,19 @@
+ 					 int, enum machine_mode));
+ 
+ extern void real_2expN		PARAMS ((REAL_VALUE_TYPE *, int));
++#endif /* 0 */
+ 
+ extern unsigned int real_hash	PARAMS ((const REAL_VALUE_TYPE *));
+ 
++extern void ereal_from_int	PARAMS ((REAL_VALUE_TYPE *,
++				       HOST_WIDE_INT, HOST_WIDE_INT,
++				       enum machine_mode));
++extern void ereal_from_uint	PARAMS ((REAL_VALUE_TYPE *,
++				       unsigned HOST_WIDE_INT,
++				       unsigned HOST_WIDE_INT,
++				       enum machine_mode));
++extern void ereal_to_int	PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *,
++				       REAL_VALUE_TYPE));
+ 
+ /* Target formats defined in real.c.  */
+ extern const struct real_format ieee_single_format;
+@@ -235,6 +270,7 @@
+ extern const struct real_format real_internal_format;
+ 
+ 
++#if 0
+ /* ====================================================================== */
+ /* Crap.  */
+ 
+@@ -318,6 +354,7 @@
+ 					 const REAL_VALUE_TYPE *, int));
+ 
+ /* **** End of software floating point emulator interface macros **** */
++#endif /* 0 */
+ 
+ /* Constant real values 0, 1, 2, and -1.  */
+ 
+diff -Naur gcc-3.3.3.orig/gcc/sdbout.c gcc-3.3.3.tigcc8/gcc/sdbout.c
+--- gcc-3.3.3.orig/gcc/sdbout.c	Tue Sep 17 08:05:52 2002
++++ gcc-3.3.3.tigcc8/gcc/sdbout.c	Thu Feb 19 21:20:04 2004
+@@ -1596,9 +1596,7 @@
+ #ifdef ASM_OUTPUT_SOURCE_LINE
+       ASM_OUTPUT_SOURCE_LINE (asm_out_file, line);
+ #else
+-      fprintf (asm_out_file, "\t.ln\t%d\n",
+-	       ((sdb_begin_function_line > -1)
+-		? line - sdb_begin_function_line : 1));
++      fprintf (asm_out_file, "\t.ln\t%d\n", last_linenum);
+ #endif
+     }
+ }
+diff -Naur gcc-3.3.3.orig/gcc/simplify-rtx.c gcc-3.3.3.tigcc8/gcc/simplify-rtx.c
+--- gcc-3.3.3.orig/gcc/simplify-rtx.c	Thu Jul  3 09:38:22 2003
++++ gcc-3.3.3.tigcc8/gcc/simplify-rtx.c	Thu Feb 19 21:20:04 2004
+@@ -435,7 +435,7 @@
+ 	lv = CONST_DOUBLE_LOW (trueop),  hv = CONST_DOUBLE_HIGH (trueop);
+ 
+       REAL_VALUE_FROM_INT (d, lv, hv, mode);
+-      d = real_value_truncate (mode, d);
++      d = REAL_VALUE_TRUNCATE (mode, d);
+       return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
+     }
+   else if (code == UNSIGNED_FLOAT && GET_MODE (trueop) == VOIDmode
+@@ -463,7 +463,7 @@
+ 	hv = 0, lv &= GET_MODE_MASK (op_mode);
+ 
+       REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode);
+-      d = real_value_truncate (mode, d);
++      d = REAL_VALUE_TRUNCATE (mode, d);
+       return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
+     }
+ 
+@@ -660,7 +660,7 @@
+ 	  d = REAL_VALUE_NEGATE (d);
+ 	  break;
+ 	case FLOAT_TRUNCATE:
+-	  d = real_value_truncate (mode, d);
++	  d = REAL_VALUE_TRUNCATE (mode, d);
+ 	  break;
+ 	case FLOAT_EXTEND:
+ 	  /* All this does is change the mode.  */
+@@ -809,8 +809,8 @@
+ 
+       REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
+       REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
+-      f0 = real_value_truncate (mode, f0);
+-      f1 = real_value_truncate (mode, f1);
++      f0 = REAL_VALUE_TRUNCATE (mode, f0);
++      f1 = REAL_VALUE_TRUNCATE (mode, f1);
+ 
+       if (code == DIV
+ 	  && !MODE_HAS_INFINITIES (mode)
+@@ -819,7 +819,7 @@
+ 
+       REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
+ 
+-      value = real_value_truncate (mode, value);
++      value = REAL_VALUE_TRUNCATE (mode, value);
+       return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
+     }
+ 
+diff -Naur gcc-3.3.3.orig/gcc/stmt.c gcc-3.3.3.tigcc8/gcc/stmt.c
+--- gcc-3.3.3.orig/gcc/stmt.c	Thu Aug 21 03:50:02 2003
++++ gcc-3.3.3.tigcc8/gcc/stmt.c	Mon Jul 19 05:31:36 2004
+@@ -542,6 +542,22 @@
+ 
+   emit_queue ();
+ 
++#if 0 /* (TIGCC 20030607) Revert the following patch:
++
++2003-03-21  Richard Henderson  <rth@redhat.com>
++
++	PR opt/2001
++	* bb-reorder.c (maybe_duplicate_computed_goto_succ): New.
++	(make_reorder_chain_1): Call it.
++
++	* function.h (struct function): Add computed_goto_common_label,
++	computed_goto_common_reg.
++	* function.c (free_after_compilation): Zap them.
++	* stmt.c (expand_computed_goto): Use them to produce one
++	indirect branch per function.
++
++because it breaks ER_throw, whereas PR opt/2001 is a compilation slowness
++problem (in an extreme case) only.  -- Kevin Kofler  */
+   if (! cfun->computed_goto_common_label)
+     {
+       cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x);
+@@ -558,6 +574,12 @@
+       emit_move_insn (cfun->computed_goto_common_reg, x);
+       emit_jump (cfun->computed_goto_common_label);
+     }
++#else /* not 0 */
++  do_pending_stack_adjust ();
++  emit_indirect_jump (x);
++  
++  current_function_has_computed_jump = 1;
++#endif /* 0 */
+ }
+ 
+ /* Handle goto statements and the labels that they can go to.  */
+@@ -5381,8 +5403,12 @@
+ 	 If the switch-index is a constant, do it this way
+ 	 because we can optimize it.  */
+ 
++/* (TIGCC 20030906) Backport fix for PR middle-end/11823 from mainline (3.4):
++                    Only use jump tables for dense switch statements when
++                    optimizing for size.  */
+       else if (count < case_values_threshold ()
+-	       || compare_tree_int (range, 10 * count) > 0
++	       || compare_tree_int (range,
++				    (optimize_size ? 3 : 10) * count) > 0
+ 	       /* RANGE may be signed, and really large ranges will show up
+ 		  as negative numbers.  */
+ 	       || compare_tree_int (range, 0) < 0
+@@ -5466,6 +5492,9 @@
+ 	      use_cost_table
+ 		= (TREE_CODE (orig_type) != ENUMERAL_TYPE
+ 		   && estimate_case_costs (thiscase->data.case_stmt.case_list));
++/* (TIGCC 20030907) Don't balance the tree when optimizing for size. A linear
++                    decision tree gives far smaller code. -- Kevin Kofler  */
++	      if (!optimize_size)
+ 	      balance_case_nodes (&thiscase->data.case_stmt.case_list, NULL);
+ 	      emit_case_nodes (index, thiscase->data.case_stmt.case_list,
+ 			       default_label, index_type);
+@@ -6101,10 +6130,17 @@
+ 	     Omit the conditional branch to default if we it avoid only one
+ 	     right child; it costs too much space to save so little time.  */
+ 
++	  /* (TIGCC 20030907) Also omit the conditional branch to default if we are
++	                      optimizing for size. -- Kevin Kofler
++         (TIGCC 20040719) But don't omit branches which are needed for
++                          correctness in case ranges. -- Kevin Kofler  */
++
+ 	  if (node->right->right || node->right->left
+ 	      || !tree_int_cst_equal (node->right->low, node->right->high))
+ 	    {
+-	      if (!node_has_low_bound (node, index_type))
++	      if (!node_has_low_bound (node, index_type)
++	          && (!optimize_size
++	              || !tree_int_cst_equal (node->right->low, node->right->high)))
+ 		{
+ 		  emit_cmp_and_jump_insns (index,
+ 					   convert_modes
+diff -Naur gcc-3.3.3.orig/gcc/toplev.c gcc-3.3.3.tigcc8/gcc/toplev.c
+--- gcc-3.3.3.orig/gcc/toplev.c	Tue Dec 23 06:28:28 2003
++++ gcc-3.3.3.tigcc8/gcc/toplev.c	Tue Jul 27 12:34:40 2004
+@@ -804,7 +804,7 @@
+ #endif
+ 
+ /* Nonzero means put zero initialized data in the bss section.  */
+-int flag_zero_initialized_in_bss = 1;
++int flag_zero_initialized_in_bss = 0; /* (TIGCC 20031012) */
+ 
+ /* Enable SSA.  */
+ int flag_ssa = 0;
+@@ -883,6 +883,12 @@
+ 
+ int flag_tracer = 0;
+ 
++/* (TIGCC) Make compound literals (cast constructors) global for backwards compatibility.  */
++int flag_global_compound_literals = 1;
++
++/* (TIGCC 20040727) When merging constants, also merge constant pools.  */
++int flag_merge_constant_pools = 1;
++
+ /* Values of the -falign-* flags: how much to align labels in code.
+    0 means `use default', 1 means `don't align'.
+    For each variable, there is an _log variant which is the power
+@@ -1184,10 +1190,16 @@
+    N_("Report time taken by each compiler pass at end of run") },
+   {"mem-report", &mem_report, 1,
+    N_("Report on permanent memory allocation at end of run") },
+-  { "trapv", &flag_trapv, 1,
++  {"trapv", &flag_trapv, 1,
+    N_("Trap for signed overflow in addition / subtraction / multiplication") },
+-  { "new-ra", &flag_new_regalloc, 1,
++  {"new-ra", &flag_new_regalloc, 1,
+    N_("Use graph coloring register allocation.") },
++  {"global-compound-literals", &flag_global_compound_literals, 1,
++   N_("Make compound literals (cast constructors) global for backwards compatibility") },
++  {"global-cast-constructors", &flag_global_compound_literals, 1,
++   N_("Make compound literals (cast constructors) global for backwards compatibility") },
++  {"merge-constant-pools", &flag_merge_constant_pools, 1,
++   N_("When merging constants, also merge constant pools") },
+ };
+ 
+ /* Table of language-specific options.  */
+@@ -2692,7 +2704,14 @@
+ 	       | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+ 
+   /* CFG is no longer maintained up-to-date.  */
+-  if (optimize)
++  /* (TIGCC 20030421) Reverted the following patch, which is a pessimization in
++                      our tests:
++      Wed Mar  5 15:45:40 CET 2003  Jan Hubicka  <jh@suse.cz>
++
++          * toplev.c (rest_of_compilation):  Do duplicate loop headers when
++            optimizing for size.
++      -- Kevin Kofler */
++  if (optimize && !optimize_size)
+     {
+       free_bb_for_insn ();
+       copy_loop_headers (insns);
+@@ -4021,6 +4040,12 @@
+     fix_register (option_value, 0, 1);
+   else if ((option_value = skip_leading_substring (arg, "call-saved-")))
+     fix_register (option_value, 0, 0);
++  else if ((option_value = skip_leading_substring (arg, "reg-relative-")))
++    {
++      fix_register (option_value, 1, 1);
++      target_flags |= MASK_REG_RELATIVE;
++      strcpy (TARGET_RELATION_REG, option_value);
++    }
+   else if ((option_value = skip_leading_substring (arg, "align-loops=")))
+     align_loops = read_integral_parameter (option_value, arg - 2, align_loops);
+   else if ((option_value = skip_leading_substring (arg, "align-functions=")))
+@@ -5020,6 +5045,11 @@
+ 	}
+     }
+ 
++  /* TIGCC Patch: Register d2 is used by the TIOS calling convention.
++     See "call-used-" further up in this file. */
++  if (TARGET_TIOS)
++    fix_register ("d2", 0, 1);
++
+   if (flag_no_inline == 2)
+     flag_no_inline = 0;
+   else
+@@ -5215,7 +5245,7 @@
+       flag_prefetch_loop_arrays = 0;
+     }
+ 
+-#ifndef OBJECT_FORMAT_ELF
++#if 0 /*ndef OBJECT_FORMAT_ELF*/ /* (TIGCC 20040619) Remove pointless warning. */
+   if (flag_function_sections && write_symbols != NO_DEBUG)
+     warning ("-ffunction-sections may affect debugging on some targets");
+ #endif
+diff -Naur gcc-3.3.3.orig/gcc/tree-inline.c gcc-3.3.3.tigcc8/gcc/tree-inline.c
+--- gcc-3.3.3.orig/gcc/tree-inline.c	Wed Jul 23 09:13:36 2003
++++ gcc-3.3.3.tigcc8/gcc/tree-inline.c	Sat Sep 25 00:47:22 2004
+@@ -1180,6 +1180,48 @@
+       return NULL_TREE;
+     }
+ 
++  /* (TIGCC 20040926) The following code by Eric Botcazou fixes an ICE when
++     inlining tries to change the mode of parameters or the return value. Eric
++     Botcazou's comments explain the details.  -- Kevin Kofler  */
++  /* We can't inline functions at a calling point where they are viewed
++     with too different a prototype than the actual one, because the
++     calling convention may not be the same on both sides.  */
++  if (TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR)
++    {
++      tree from_ftype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
++      tree to_ftype = TREE_TYPE (fn);
++
++      if (from_ftype != to_ftype)
++	{
++	  tree from_arg, to_arg;
++
++	  /* If the calling point expects a return value and it is too
++	     different from the one actually returned, don't inline.  */
++	  if (! VOID_TYPE_P (TREE_TYPE (from_ftype))
++	      && TYPE_MODE (TREE_TYPE (from_ftype))
++		 != TYPE_MODE (TREE_TYPE (to_ftype)))
++	    return NULL_TREE;
++
++	  /* If the calling point doesn't pass at least the correct
++	     number of arguments with the correct modes, don't inline.
++	     Objective-C appears to add a trailing void parameter at
++	     the calling point under certain circumstances.  */
++	  from_arg = TYPE_ARG_TYPES (from_ftype);
++	  to_arg = TYPE_ARG_TYPES (to_ftype);
++
++	  while (to_arg)
++	    {
++	      if (! from_arg
++		  || TYPE_MODE (TREE_VALUE (from_arg))
++		     != TYPE_MODE (TREE_VALUE (to_arg)))
++		return NULL_TREE;
++
++	      from_arg = TREE_CHAIN (from_arg);
++	      to_arg = TREE_CHAIN (to_arg);
++	    }
++	}
++    }
++
+   if (! (*lang_hooks.tree_inlining.start_inlining) (fn))
+     return NULL_TREE;
+ 
+diff -Naur gcc-3.3.3.orig/gcc/tree.c gcc-3.3.3.tigcc8/gcc/tree.c
+--- gcc-3.3.3.orig/gcc/tree.c	Thu Jan 29 18:58:12 2004
++++ gcc-3.3.3.tigcc8/gcc/tree.c	Thu Feb 19 21:20:04 2004
+@@ -830,7 +830,7 @@
+ 
+   return ((TREE_CODE (expr) == REAL_CST
+ 	   && ! TREE_CONSTANT_OVERFLOW (expr)
+-	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
++	   && REAL_VALUE_ISZERO (TREE_REAL_CST (expr)))
+ 	  || (TREE_CODE (expr) == COMPLEX_CST
+ 	      && real_zerop (TREE_REALPART (expr))
+ 	      && real_zerop (TREE_IMAGPART (expr))));
+diff -Naur gcc-3.3.3.orig/gcc/unroll.c gcc-3.3.3.tigcc8/gcc/unroll.c
+--- gcc-3.3.3.orig/gcc/unroll.c	Mon Dec  1 22:00:12 2003
++++ gcc-3.3.3.tigcc8/gcc/unroll.c	Thu Feb 19 21:20:04 2004
+@@ -326,6 +326,11 @@
+ #ifdef HAVE_cc0
+ 	  rtx prev = PREV_INSN (last_loop_insn);
+ #endif
++
++/* (TIGCC 20030605) Moved this up in order to prevent reachable insns from
++                    being mistaken as unreachable. -- Kevin Kofler */
++	  delete_related_insns (ujump);
++
+ 	  delete_related_insns (last_loop_insn);
+ #ifdef HAVE_cc0
+ 	  /* The immediately preceding insn may be a compare which must be
+@@ -334,8 +339,6 @@
+ 	    delete_related_insns (prev);
+ #endif
+ 
+-	  delete_related_insns (ujump);
+-
+ 	  /* Remove the loop notes since this is no longer a loop.  */
+ 	  if (loop->vtop)
+ 	    delete_related_insns (loop->vtop);
+@@ -3933,6 +3936,23 @@
+      (abs_diff + abs_inc - 1) / abs_inc, provided care was taken to
+      handle potential overflow of the summation.  */
+   loop_info->n_iterations = abs_diff / abs_inc + ((abs_diff % abs_inc) != 0);
++
++  /* (TIGCC 20031228) If the first instruction in the loop is a jump to cont,
++                      then we actually have 1 iteration less.
++                      And if we end up with no iteration at all, delete the jump
++                      at the end of the loop so the dead code elimination passes
++                      will eliminate the useless loop. -- Kevin Kofler */
++  if (loop->cont) {
++    rtx first_loop_insn = NEXT_INSN (loop->start);
++    if (GET_CODE (first_loop_insn) == JUMP_INSN
++        && INSN_LUID (JUMP_LABEL (first_loop_insn))
++           == INSN_LUID (NEXT_INSN (loop->cont))) {
++      loop_info->n_iterations--;
++      if (!loop_info->n_iterations)
++        delete_related_insns (last_loop_insn);
++    }    
++  }
++
+   return loop_info->n_iterations;
+ }
+ 
+diff -Naur gcc-3.3.3.orig/gcc/varasm.c gcc-3.3.3.tigcc8/gcc/varasm.c
+--- gcc-3.3.3.orig/gcc/varasm.c	Mon Jan 12 18:23:08 2004
++++ gcc-3.3.3.tigcc8/gcc/varasm.c	Sun Aug  8 07:27:00 2004
+@@ -221,6 +221,46 @@
+ EXTRA_SECTION_FUNCTIONS
+ #endif
+ 
++/* (TIGCC 20040725) Moved these up. We need those upwards. And besides, they are
++                    _declarations_, so what were they doing in the middle of the
++                    file??? -- Kevin Kofler  */
++enum section_category
++{
++  SECCAT_TEXT,
++
++  SECCAT_RODATA,
++  SECCAT_RODATA_MERGE_STR,
++  SECCAT_RODATA_MERGE_STR_INIT,
++  SECCAT_RODATA_MERGE_CONST,
++  SECCAT_SRODATA,
++
++  SECCAT_DATA,
++
++  /* To optimize loading of shared programs, define following subsections
++     of data section:
++	_REL	Contains data that has relocations, so they get grouped
++		together and dynamic linker will visit fewer pages in memory.
++	_RO	Contains data that is otherwise read-only.  This is useful
++		with prelinking as most relocations won't be dynamically
++		linked and thus stay read only.
++	_LOCAL	Marks data containing relocations only to local objects.
++		These relocations will get fully resolved by prelinking.  */
++  SECCAT_DATA_REL,
++  SECCAT_DATA_REL_LOCAL,
++  SECCAT_DATA_REL_RO,
++  SECCAT_DATA_REL_RO_LOCAL,
++
++  SECCAT_SDATA,
++  SECCAT_TDATA,
++
++  SECCAT_BSS,
++  SECCAT_SBSS,
++  SECCAT_TBSS
++};
++
++static enum section_category
++categorize_decl_for_section PARAMS ((tree, int, int));
++
+ /* Tell assembler to switch to text section.  */
+ 
+ void
+@@ -590,7 +630,26 @@
+      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+      unsigned int flags ATTRIBUTE_UNUSED;
+ {
+-#ifdef HAVE_GAS_SHF_MERGE
++/* (TIGCC 20040725) Implement string merging for TIGCC-extended COFF.
++                    We only handle 2 cases: aligned or unaligned.
++                    SECTION_STRINGS is abused for the unaligned flag. */
++  if (flag_merge_constants
++      && TREE_CODE (decl) == STRING_CST
++      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
++    {
++      if (align == 8)
++        {
++          named_section_flags (".rodata.__unalignedstr", flags | SECTION_MERGE | SECTION_STRINGS);
++          return;
++        }
++      else if (align == 16)
++        {
++          named_section_flags (".rodata.__alignedstr", flags | SECTION_MERGE);
++          return;
++        }
++    }
++
++#if 0 /*def HAVE_GAS_SHF_MERGE*/
+   if (flag_merge_constants
+       && TREE_CODE (decl) == STRING_CST
+       && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+@@ -665,7 +724,25 @@
+      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+      unsigned int flags ATTRIBUTE_UNUSED;
+ {
+-#ifdef HAVE_GAS_SHF_MERGE
++/* (TIGCC 20040725) Implement constant merging for TIGCC-extended COFF.
++                    We only handle 2 cases: aligned or unaligned.
++                    SECTION_STRINGS is abused for the unaligned flag. */
++  if (flag_merge_constants
++      && mode != VOIDmode)
++    {
++      if (align == 8)
++        {
++          named_section_flags (".rodata.__unalignedcst", flags | SECTION_MERGE | SECTION_STRINGS);
++          return;
++        }
++      else if (align == 16)
++        {
++          named_section_flags (".rodata.__alignedcst", flags | SECTION_MERGE);
++          return;
++        }
++    }
++
++#if 0 /*def HAVE_GAS_SHF_MERGE*/
+   unsigned int modesize = GET_MODE_BITSIZE (mode);
+ 
+   if (flag_merge_constants
+@@ -1368,7 +1445,15 @@
+ 
+   if (destination == asm_dest_bss)
+     globalize_decl (decl);
+-  resolve_unique_section (decl, 0, flag_data_sections);
++  /* (TIGCC 20040620) Common symbols are handled by our linker as separate
++     sections, so there is no point in manually creating separate BSS sections
++     under -fdata-sections. The TARGET_NO_BSS check here is a hack (it should
++     not be in supposedly target-independent code), but it is necessary because
++     -mno-bss would otherwise compact everything into a single huge section.
++                                                             -- Kevin Kofler */
++  resolve_unique_section (decl, 0, flag_data_sections
++                                   && ((destination == asm_dest_bss)
++                                       || TARGET_NO_BSS));
+ 
+   if (flag_shared_data)
+     {
+@@ -1569,7 +1654,15 @@
+     reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
+   else if (DECL_INITIAL (decl))
+     reloc = output_addressed_constants (DECL_INITIAL (decl));
+-  resolve_unique_section (decl, reloc, flag_data_sections);
++  /* (TIGCC 20040620) See the note about common symbols above. -- Kevin Kofler */
++  resolve_unique_section (decl, reloc, flag_data_sections
++                                       && (!((!TREE_PUBLIC(decl) || DECL_COMMON(decl))
++                                             && (DECL_INITIAL (decl) == 0
++                                                 || DECL_INITIAL (decl) == error_mark_node
++                                                 || (flag_zero_initialized_in_bss
++                                                     && !TREE_READONLY (decl)
++                                                     && initializer_zerop (DECL_INITIAL (decl)))))
++                                           || TARGET_NO_BSS));
+ 
+   /* Handle uninitialized definitions.  */
+ 
+@@ -2023,6 +2116,13 @@
+ 	  assemble_integer (GEN_INT (data[2]), 4, nalign, 1);
+ 	  assemble_integer (GEN_INT (data[3]), 4, nalign, 1);
+ 	  break;
++    case BFmode:
++	  /* This is how to output a SMAP BCD real constant. */
++	  REAL_VALUE_TO_TARGET_SMAP_BCD (d, data);
++	  assemble_integer (GEN_INT (data[0]), 2, align, 1);
++	  assemble_integer (GEN_INT (data[1]), 4, nalign, 1);
++	  assemble_integer (GEN_INT (data[2]), 4, nalign, 1);
++	  break;
+ 	default:
+ 	  abort ();
+ 	}
+@@ -2251,6 +2351,9 @@
+   int len, i;
+   enum tree_code code = TREE_CODE (exp);
+ 
++  if (!code)
++    abort();
++
+   /* Either set P and LEN to the address and len of something to hash and
+      exit the switch or return a value.  */
+ 
+@@ -2953,6 +3056,9 @@
+ 
+ 	  value->mode = GET_MODE (x);
+ 
++	  value->un.du.exponent = r->exponent;
++	  value->un.du.mantissa = r->mantissa;
++#if 0
+ 	  /* Copy the REAL_VALUE_TYPE by members so that we don't
+ 	     copy garbage from the original structure into our
+ 	     carefully cleaned hashing structure.  */
+@@ -2972,6 +3078,7 @@
+ 	    default:
+ 	      abort ();
+ 	    }
++#endif /* 0 */
+ 	}
+       else
+ 	{
+@@ -3016,6 +3123,9 @@
+ 	        /* Copy the REAL_VALUE_TYPE by members so that we don't
+ 	           copy garbage from the original structure into our
+ 	           carefully cleaned hashing structure.  */
++	        d->exponent = r->exponent;
++	        d->mantissa = r->mantissa;
++#if 0
+ 	        d->class = r->class;
+ 	        d->sign = r->sign;
+ 	        switch (r->class)
+@@ -3032,6 +3142,7 @@
+ 	          default:
+ 	            abort ();
+ 	          }
++#endif /* 0 */
+ 	      }
+ 	  }
+ 	else
+@@ -3445,7 +3556,18 @@
+ 	}
+ 
+       /* First switch to correct section.  */
+-      (*targetm.asm_out.select_rtx_section) (pool->mode, x, pool->align);
++      if (flag_merge_constants && flag_merge_constant_pools)
++      {
++        /* (TIGCC 20040727) If we want to merge constant pools, we need to
++                            create a separate section for each constant pool.
++                            -- Kevin Kofler  */
++        char name[strlen(fnname)+15];
++
++        sprintf (name, ".rodata.%s.cpool", fnname);
++        named_section_flags (name, SECTION_MERGE);
++      }
++      else
++        (*targetm.asm_out.select_rtx_section) (pool->mode, x, pool->align);
+ 
+ #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
+       ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode,
+@@ -3724,10 +3846,18 @@
+     case MINUS_EXPR:
+       reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
+       reloc2 = output_addressed_constants (TREE_OPERAND (exp, 1));
++#if 0
+       /* The difference of two local labels is computable at link time.  */
++      /* (TIGCC 20040808) That's true, but it is still not valid in a mergeable
++         section. GCC doesn't seem to accept that as a constant anyway (at least
++         in C), but it is never a good idea to let a latent problem just lie
++         around. And besides, this code is unsafe, consider (addr1+addr2)-addr3.
++         Still a potentially valid expression for the assembler and linker, but
++         mishandled awfully by this code. -- Kevin Kofler  */
+       if (reloc == 1 && reloc2 == 1)
+ 	reloc = 0;
+       else
++#endif /* 0 */
+ 	reloc |= reloc2;
+       break;
+ 
+@@ -4929,6 +5059,19 @@
+ 	  || strcmp (name, ".preinit_array") == 0))
+     flags |= SECTION_NOTYPE;
+ 
++/* (TIGCC 20040725) This was mostly copied out of the ELF section selector. It
++                    handles mergeable sections. -- Kevin Kofler */
++  switch (categorize_decl_for_section (decl, reloc, shlib))
++    {
++    case SECCAT_RODATA_MERGE_STR:
++    case SECCAT_RODATA_MERGE_STR_INIT:
++    case SECCAT_RODATA_MERGE_CONST:
++      flags |= SECTION_MERGE;
++      break;
++    default:
++      break;
++    }
++
+   return flags;
+ }
+ 
+@@ -5066,6 +5209,21 @@
+ {
+   bool readonly = false;
+ 
++/* (TIGCC 20040725) This was copied out of the ELF section selector. It handles
++                    mergeable sections. -- Kevin Kofler */
++  switch (categorize_decl_for_section (decl, reloc, flag_pic))
++    {
++    case SECCAT_RODATA_MERGE_STR:
++      mergeable_string_section (decl, align, 0);
++      break;
++    case SECCAT_RODATA_MERGE_STR_INIT:
++      mergeable_string_section (DECL_INITIAL (decl), align, 0);
++      break;
++    case SECCAT_RODATA_MERGE_CONST:
++      mergeable_constant_section (DECL_MODE (decl), align, 0);
++      break;
++    default:
++
+   if (DECL_P (decl))
+     {
+       if (decl_readonly_section (decl, reloc))
+@@ -5073,11 +5231,24 @@
+     }
+   else if (TREE_CODE (decl) == CONSTRUCTOR)
+     {
+-      if (! ((flag_pic && reloc)
+-	     || !TREE_READONLY (decl)
++      /* (TIGCC 20040727) Put compound literals in mergeable sections in global
++                          compound literal mode. -- Kevin Kofler
++         (TIGCC 20040808) But not if they contain relocations. -- Kevin Kofler */
++      if (! (reloc
++	     || (!TREE_READONLY (decl) && !flag_global_compound_literals)
+ 	     || TREE_SIDE_EFFECTS (decl)
+ 	     || !TREE_CONSTANT (decl)))
+-	readonly = true;
++        {
++          mergeable_constant_section (DECL_MODE (decl), align, 0);
++          break;
++        }
++    }
++  /* (TIGCC 20040727) Put complex literals in mergeable sections.
++                      -- Kevin Kofler */
++  else if (TREE_CODE (decl) == COMPLEX_CST)
++    {
++      mergeable_constant_section (DECL_MODE (decl), align, 0);
++      break;
+     }
+   else if (TREE_CODE (decl) == STRING_CST)
+     readonly = !flag_writable_strings;
+@@ -5088,48 +5259,12 @@
+     readonly_data_section ();
+   else
+     data_section ();
++  } /* end of switch-case */
+ }
+ 
+ /* A helper function for default_elf_select_section and
+    default_elf_unique_section.  Categorizes the DECL.  */
+ 
+-enum section_category
+-{
+-  SECCAT_TEXT,
+-
+-  SECCAT_RODATA,
+-  SECCAT_RODATA_MERGE_STR,
+-  SECCAT_RODATA_MERGE_STR_INIT,
+-  SECCAT_RODATA_MERGE_CONST,
+-  SECCAT_SRODATA,
+-
+-  SECCAT_DATA,
+-
+-  /* To optimize loading of shared programs, define following subsections
+-     of data section:
+-	_REL	Contains data that has relocations, so they get grouped
+-		together and dynamic linker will visit fewer pages in memory.
+-	_RO	Contains data that is otherwise read-only.  This is useful
+-		with prelinking as most relocations won't be dynamically
+-		linked and thus stay read only.
+-	_LOCAL	Marks data containing relocations only to local objects.
+-		These relocations will get fully resolved by prelinking.  */
+-  SECCAT_DATA_REL,
+-  SECCAT_DATA_REL_LOCAL,
+-  SECCAT_DATA_REL_RO,
+-  SECCAT_DATA_REL_RO_LOCAL,
+-
+-  SECCAT_SDATA,
+-  SECCAT_TDATA,
+-
+-  SECCAT_BSS,
+-  SECCAT_SBSS,
+-  SECCAT_TBSS
+-};
+-
+-static enum section_category
+-categorize_decl_for_section PARAMS ((tree, int, int));
+-
+ static enum section_category
+ categorize_decl_for_section (decl, reloc, shlib)
+      tree decl;
+@@ -5150,7 +5285,12 @@
+   else if (TREE_CODE (decl) == VAR_DECL)
+     {
+       if (DECL_INITIAL (decl) == NULL
+-	  || DECL_INITIAL (decl) == error_mark_node)
++	  || DECL_INITIAL (decl) == error_mark_node
++/* (TIGCC 20040620) Someone forgot about -fzero-initialized-in-bss here...
++                    -- Kevin Kofler */
++	  || (flag_zero_initialized_in_bss
++	      && !TREE_READONLY (decl)
++	      && initializer_zerop (DECL_INITIAL (decl))))
+ 	ret = SECCAT_BSS;
+       else if (! TREE_READONLY (decl)
+ 	       || TREE_SIDE_EFFECTS (decl)
+diff -Naur gcc-3.3.3.orig/gcc/version.c gcc-3.3.3.tigcc8/gcc/version.c
+--- gcc-3.3.3.orig/gcc/version.c	Sat Feb 14 20:20:58 2004
++++ gcc-3.3.3.tigcc8/gcc/version.c	Sat Sep 25 00:22:34 2004
+@@ -6,7 +6,7 @@
+    please modify this string to indicate that, e.g. by putting your
+    organization's name in parentheses at the end of the string.  */
+ 
+-const char version_string[] = "3.3.3";
++const char version_string[] = "3.3.3-tigcc-8";
+ 
+ /* This is the location of the online document giving instructions for
+    reporting bugs.  If you distribute a modified version of GCC,
+@@ -15,4 +15,4 @@
+    forward us bugs reported to you, if you determine that they are
+    not bugs in your modifications.)  */
+ 
+-const char bug_report_url[] = "<URL:http://gcc.gnu.org/bugs.html>";
++const char bug_report_url[] = "http://tigcc.ticalc.org/";

+ 61 - 0
tigcc/general/FileReadToBufferThreadUnit.pas

@@ -0,0 +1,61 @@
+unit FileReadToBufferThreadUnit;
+
+interface
+
+uses
+	SysUtils, Classes, Windows, Forms, Controls, SyncObjs;
+
+type
+	TFileReadToBufferThread = class(TThread)
+	private
+		FHasTerminated: Boolean;
+		FFileHandle: THandle;
+		FBufferStream: TStream;
+		FLock: TMultiReadExclusiveWriteSynchronizer;
+	protected
+		procedure Execute; override;
+	public
+		constructor Create(FileHandle: THandle; BufferStream: TStream);
+		destructor Destroy; override;
+		property HasTerminated: Boolean read FHasTerminated;
+		property Lock: TMultiReadExclusiveWriteSynchronizer read FLock;
+	end;
+
+implementation
+
+const
+	BytesToRead = 256;
+
+{ THandleWaitThread }
+
+constructor TFileReadToBufferThread.Create(FileHandle: HFile; BufferStream: TStream);
+begin
+	inherited Create (True);
+	FLock := TMultiReadExclusiveWriteSynchronizer.Create;
+	FHasTerminated := False;
+	FreeOnTerminate := False;
+	FFileHandle := FileHandle;
+	FBufferStream := BufferStream;
+	Resume;
+end;
+
+destructor TFileReadToBufferThread.Destroy;
+begin
+	FLock.Free;
+	inherited;
+end;
+
+procedure TFileReadToBufferThread.Execute;
+var
+	Buffer: array [1..BytesToRead] of Byte;
+	Count: Cardinal;
+begin
+	while (not Terminated) and ReadFile (FFileHandle, Buffer, BytesToRead, Count, nil) do begin
+		Lock.BeginWrite;
+		FBufferStream.Write (Buffer, Count);
+		Lock.EndWrite;
+	end;
+	FHasTerminated := True;
+end;
+
+end.

+ 40 - 0
tigcc/general/HandleWaitThreadUnit.pas

@@ -0,0 +1,40 @@
+unit HandleWaitThreadUnit;
+
+interface
+
+uses
+	SysUtils, Classes, Windows, Forms, Controls;
+
+type
+	THandleWaitThread = class(TThread)
+	private
+		FHasTerminated: Boolean;
+		FWaitHandle: THandle;
+	protected
+		procedure Execute; override;
+	public
+		property WaitHandle: THandle read FWaitHandle;
+		property HasTerminated: Boolean read FHasTerminated;
+		constructor Create(WaitHandle: THandle);
+	end;
+
+implementation
+
+{ THandleWaitThread }
+
+constructor THandleWaitThread.Create(WaitHandle: THandle);
+begin
+	inherited Create (True);
+	FHasTerminated := False;
+	FreeOnTerminate := False;
+	FWaitHandle := WaitHandle;
+	Resume;
+end;
+
+procedure THandleWaitThread.Execute;
+begin
+	while (not Terminated) and (WaitForSingleObject (FWaitHandle, 1000) = Wait_TimeOut) do;
+	FHasTerminated := True;
+end;
+
+end.

+ 698 - 0
tigcc/general/ObjList.pas

@@ -0,0 +1,698 @@
+unit ObjList;
+
+{
+
+Unit ObjList
+Copyright (c) 2000-2001 Sebastian Reichelt
+
+Objekt-Listen für Objektorientierte Programmierung nach den Regeln des
+Software Engineering
+
+
+TObjectList
+	TObjectList ist die Basisklasse für Objektlisten. Sie stellt alle
+	Eigenschaften und Methoden für eine abstrakte Liste von Objekten zur
+	Verfügung. Sie ähnelt TList, wobei statt Zeigern Objekte eingefügt
+	werden können.
+	TObjectList sollte nur zum akuten Abspeichern einer bestimmten Auswahl
+	an Objekten benutzt werden. Für alle weiteren Aufgaben stehen die
+	anderen Listen zur Verfügung.
+
+TObjectContainer
+	Jedes Objekt, das parallel zu anderen gleichartigen Objekten dynamisch
+	erzeugt wird, benötigt ein übergeordnetes Objekt (Owner), das sämtliche
+	dynamischen Objekte verwaltet.
+	Ein solches übergeordnetes Objekt sollte ein Objekt der Klasse
+	TObjectContainer oder einer davon abgeleiteten Klasse sein. Die
+	dynamischen Objekte müssen dann von TContainerItem abgeleitet und beim
+	Erstellen der übergeordnete Container als Parameter an den Constructor
+	Create übergeben werden.
+	Beim Freigeben oder Leeren (Clear) des Containers werden dann alle
+	untergeordneten Objekte aus dem Speicher entfernt. Ebenso wird beim
+	Freigeben eines untergeordneten Objektes dieses aus dem Container
+	gelöscht.
+	Um bei einem untergeordneten Objekt den Container zu wechseln, müssen
+	Sie einfach der Eigenschaft Owner einen neuen Wert zuweisen. Der Owner
+	kann auch NIL sein, dann handelt es sich um ein ganz normales Objekt.
+	Mit PerformItemAction kann eine Integer-Konstante als Aktion an alle
+	untergeordneten Objekte übergeben werden. Dort wird dann die virtuelle
+	Methode PerformAction aufgerufen, die das Ereignis OnAction auslöst.
+	Da diese Klasse von TCollection abgeleitet wurde, wird das Objekt in
+	die Stream-Komponentenspeicherung mit einbezogen.
+
+TConnectionList
+	Um ein Objekt auf bestimmte Weise mit einem oder mehreren anderen zu
+	verbinden, muß jedem der Objekte eine TConnectionList hinzugefügt werden.
+	Die Verbindung zwischen zwei Objekten kann dann hergestellt werden,
+	indem man die Klassenmethode ConnectLists mit den beiden Listen der
+	Objekte als Parameter aufruft. Mit DisconnectLists läßt sich die
+	Verbindung wieder aufheben. Alternativ dazu kann man auch die Methode
+	ConnectTo bzw. DisconnectFrom einer der beiden Listen verwenden.
+	Auch bei dieser Klasse gibt es eine Methode PerformItemAction, die bei
+	allen verknüpften Listen ein OnAction-Ereignis auslöst (s.o.).
+	Auch diese Klasse wurde in die Stream-Speicherung einbezogen.
+
+TReferenceList
+	Bei TReferenceList handelt es sich um eine spezielle Form der akuten
+	Objektliste. Sie wird benutzt, wenn ein Objekt, das sich in einem
+	Container befindet, genau ein Objekt eines bestimmten Typs referenzieren
+	muß, dieses eine Objekt aber beliebig viele andere referenzieren kann.
+	Dieses Objekt muß dann selbstverständlich an den Konstruktor des
+	ContainerItem übergeben und dann in das private Symbol einer
+	Eigenschaft eingetragen werden. Außerdem muß das erstellte ContainerItem
+	mit der Methode Add in eine Liste des Typs TReferenceList des zu
+	referenzierenden Objekts eingetragen werden. Ebenso muß es beim
+	Entfernen mit Delete wieder ausgetragen werden. Das funktioniert auch
+	mit akuten Listen, aber bei TReferenceList ergeben sich einige Vorteile.
+	Neu ist, daß beim Entfernen eines Objekts mit Referenzliste(n) alle
+	referenzierten Objekte (die ContainerItems irgendeines beliebigen
+	Containers sind) gelöscht werden. Das gleiche geschieht beim Aufruf von
+	Clear.
+	Auch neu ist der gewohnte Einsatz von PerformItemAction bei einer
+	Referenzliste.
+	TReferenceList wird nicht automatisch gespeichert. Die Instanzen sollten
+	daher automatisch verwaltet werden.
+
+}
+
+{$WEAKPACKAGEUNIT}
+
+interface
+
+uses
+	Classes;
+
+type
+	TObjectNotifyEvent = procedure(Sender, Item: TObject) of object;
+
+	TOwnedPersistent = class(TPersistent)
+	private
+		FOwner: TPersistent;
+	protected
+		procedure SetOwner(const Value: TPersistent); virtual;
+		function GetOwner: TPersistent; override;
+	public
+		constructor Create(AOwner: TPersistent); virtual;
+		destructor Destroy; override;
+		property Owner: TPersistent read FOwner write SetOwner;
+	published
+	end;
+
+	TObjectList = class(TList)
+	private
+		FOwner: TObject;
+	protected
+		function Get(Index: Integer): TObject;
+		procedure Put(Index: Integer; Item: TObject);
+	public
+		constructor Create(AOwner: TObject);
+		function Add(Item: TObject): Integer;
+		procedure Insert(Index: Integer; Item: TObject);
+		procedure Delete(Index: Integer); overload;
+		procedure Delete(Item: TObject); overload;
+		procedure Remove(Item: TObject);
+		function IndexOf(Item: TObject): Integer;
+		function First: TObject;
+		function Last: TObject;
+		property Items[Index: Integer]: TObject read Get write Put; default;
+		property Owner: TObject read FOwner;
+	end;
+
+	TContainerItem = class;
+
+	TActionNotifyEvent = procedure(Sender: TObject; Action: Integer; Obj: TObject) of object;
+	TSubItemNotifyEvent = procedure(Sender: TObject; Item: TContainerItem) of object;
+
+	TReferenceList = class(TObjectList)
+	private
+		FOnAdd: TSubItemNotifyEvent;
+		FOnDelete: TSubItemNotifyEvent;
+		function Get(Index: Integer): TContainerItem;
+	protected
+	public
+		destructor Destroy; override;
+		procedure Clear; override;
+		procedure Add(Item: TContainerItem);
+		procedure Delete(Item: TContainerItem);
+		procedure PerformItemAction(Action: Integer; Obj: TObject = nil); virtual;
+		function IndexOf(Item: TContainerItem): Integer;
+		property Items[Index: Integer]: TContainerItem read Get; default;
+		property OnAdd: TSubItemNotifyEvent read FOnAdd write FOnAdd;
+		property OnDelete: TSubItemNotifyEvent read FOnDelete write FOnDelete;
+	end;
+
+	TObjectContainer = class(TOwnedCollection)
+	private
+	protected
+	public
+		procedure PerformItemAction(Action: Integer; Obj: TObject = nil); virtual;
+	end;
+
+	TContainerItem = class(TCollectionItem)
+	private
+		FOnAction: TActionNotifyEvent;
+		function GetItemOwner: TObjectContainer;
+		procedure SetItemOwner(const Value: TObjectContainer);
+	protected
+		procedure PerformAction(Action: Integer; Obj: TObject); virtual;
+	public
+		property Owner: TObjectContainer read GetItemOwner write SetItemOwner;
+		property OnAction: TActionNotifyEvent read FOnAction write FOnAction;
+	end;
+
+	TFastContainerItem = class;
+	TFastContainerItemClass = class of TFastContainerItem;
+
+	TFastObjectContainer = class(TObject)
+	private
+		FOwner: TPersistent;
+		FItems: TObjectList;
+		FCount: Integer;
+		FItemClass: TFastContainerItemClass;
+	protected
+		procedure InsertItem(Item: TFastContainerItem);
+		procedure RemoveItem(Item: TFastContainerItem);
+		function GetItem(Index: Integer): TFastContainerItem;
+	public
+		constructor Create(AOwner: TPersistent; ItemClass: TFastContainerItemClass);
+		destructor Destroy; override;
+		property Owner: TPersistent read FOwner;
+		function Add: TFastContainerItem;
+		procedure Clear;
+		function Insert(Index: Integer): TFastContainerItem;
+		property Count: Integer read FCount;
+		property ItemClass: TFastContainerItemClass read FItemClass;
+		property Items[Index: Integer]: TFastContainerItem read GetItem;
+		procedure PerformItemAction(Action: Integer; Obj: TObject = nil); virtual;
+	end;
+
+	TFastContainerItem = class(TPersistent)
+	private
+		FOnAction: TActionNotifyEvent;
+		FCollection: TFastObjectContainer;
+		function GetIndex: Integer;
+		procedure SetIndex(const Value: Integer);
+		procedure SetCollection(const Value: TFastObjectContainer);
+	protected
+		procedure PerformAction(Action: Integer; Obj: TObject); virtual;
+	public
+		constructor Create(Collection: TFastObjectContainer); virtual;
+		destructor Destroy; override;
+		property Owner: TFastObjectContainer read FCollection write SetCollection;
+		property Collection: TFastObjectContainer read FCollection write SetCollection;
+		property Index: Integer read GetIndex write SetIndex;
+		property OnAction: TActionNotifyEvent read FOnAction write FOnAction;
+	end;
+
+	TConnectionList = class;
+
+	TConItem = class(TCollectionItem)
+	private
+		function GetOtherItem: TConItem;
+	protected
+		FConList: TConnectionList;
+		FOtherItem: TConItem;
+		procedure SetConList(const Value: TConnectionList); virtual;
+	public
+		destructor Destroy; override;
+		property OtherItem: TConItem read GetOtherItem;
+	//published
+		property ConList: TConnectionList read FConList write SetConList;
+	end;
+
+	{$WARNINGS OFF}
+	TConCollection = class(TOwnedCollection)
+	private
+		function GetNewOwner: TConnectionList;
+	public
+		function SearchForList(List: TConnectionList): TConItem;
+		property Owner: TConnectionList read GetNewOwner;
+	end;
+	{$WARNINGS ON}
+
+	TConnectionNotifyEvent = procedure(Sender: TObject; Item: TConnectionList) of object;
+
+	TConnectionList = class(TOwnedPersistent)
+	private
+		FCollection: TConCollection;
+		FOnConnect: TConnectionNotifyEvent;
+		FOnDisconnect: TConnectionNotifyEvent;
+		FOnAction: TActionNotifyEvent;
+		function GetCount: Integer;
+		procedure SetCollection(const Value: TConCollection);
+	protected
+		procedure CreateCollection(AItemClass: TCollectionItemClass); virtual;
+		procedure Add(Item: TConnectionList);
+		procedure Delete(Item: TConnectionList);
+		procedure PerformAction(Action: Integer; Obj: TObject = nil); virtual;
+	public
+		class procedure ConnectLists(List1, List2: TConnectionList);
+		class procedure DisconnectLists(List1, List2: TConnectionList);
+		constructor Create(AOwner: TPersistent); override;
+		constructor CreateSpecial(AOwner: TPersistent; AItemClass: TCollectionItemClass); virtual;
+		destructor Destroy; override;
+		procedure Clear;
+		procedure PerformItemAction(Action: Integer; Obj: TObject); virtual;
+		procedure ConnectTo(List: TConnectionList);
+		procedure DisconnectFrom(List: TConnectionList);
+		function IsConnectedTo(List: TConnectionList): Boolean;
+		property Count: Integer read GetCount;
+		property OnConnect: TConnectionNotifyEvent read FOnConnect write FOnConnect;
+		property OnDisconnect: TConnectionNotifyEvent read FOnDisconnect write FOnDisconnect;
+		property OnAction: TActionNotifyEvent read FOnAction write FOnAction;
+	published
+		property Collection: TConCollection read FCollection write SetCollection;
+	end;
+
+implementation
+
+{ TObjectList }
+
+function TObjectList.Add(Item: TObject): Integer;
+begin
+	Result := inherited Add (Pointer (Item));
+end;
+
+procedure TObjectList.Delete(Index: Integer);
+begin
+	inherited Delete (Index);
+end;
+
+procedure TObjectList.Delete(Item: TObject);
+begin
+	if Count > 0 then begin
+		if Item = Last then
+			inherited Delete (Count - 1)
+		else
+			inherited Delete (IndexOf (Item));
+	end;
+end;
+
+function TObjectList.Get(Index: Integer): TObject;
+begin
+	Result := TObject (inherited Get (Index));
+end;
+
+function TObjectList.IndexOf(Item: TObject): Integer;
+begin
+	Result := inherited IndexOf (Pointer (Item));
+end;
+
+procedure TObjectList.Insert(Index: Integer; Item: TObject);
+begin
+	inherited Insert (Index, Pointer (Item));
+end;
+
+procedure TObjectList.Put(Index: Integer; Item: TObject);
+begin
+	inherited Put (Index, Pointer (Item));
+end;
+
+constructor TObjectList.Create(AOwner: TObject);
+begin
+	inherited Create;
+	FOwner := AOwner;
+end;
+
+function TObjectList.First: TObject;
+begin
+	Result := Get (0);
+end;
+
+function TObjectList.Last: TObject;
+begin
+	Result := Get (Count - 1);
+end;
+
+procedure TObjectList.Remove(Item: TObject);
+begin
+	Delete (Item);
+end;
+
+{ TReferenceList }
+
+procedure TReferenceList.Add(Item: TContainerItem);
+begin
+	if IndexOf (Item) < 0 then begin
+		if Assigned (FOnAdd) then
+			FOnAdd (Self, Item);
+		inherited Add (Item);
+	end;
+end;
+
+procedure TReferenceList.Clear;
+var
+	I: Integer;
+begin
+	for I := Count - 1 downto 0 do
+		Items[I].Free;
+	inherited;
+end;
+
+procedure TReferenceList.Delete(Item: TContainerItem);
+begin
+	if Assigned (FOnDelete) then
+		FOnDelete (Self, Item);
+	inherited Delete (Item);
+end;
+
+destructor TReferenceList.Destroy;
+begin
+	Clear;
+	inherited;
+end;
+
+function TReferenceList.Get(Index: Integer): TContainerItem;
+begin
+	Result := TContainerItem (inherited Get (Index));
+end;
+
+function TReferenceList.IndexOf(Item: TContainerItem): Integer;
+begin
+	Result := inherited IndexOf (Item);
+end;
+
+procedure TReferenceList.PerformItemAction(Action: Integer; Obj: TObject);
+var
+	I: Integer;
+begin
+	for I := Count - 1 downto 0 do
+		Items[I].PerformAction(Action, Obj);
+end;
+
+{ TContainerItem }
+
+function TContainerItem.GetItemOwner: TObjectContainer;
+begin
+	Result := TObjectContainer (Collection);
+end;
+
+procedure TContainerItem.PerformAction(Action: Integer; Obj: TObject);
+begin
+	if Assigned (FOnAction) then
+		FOnAction (Self, Action, Obj);
+end;
+
+procedure TContainerItem.SetItemOwner(const Value: TObjectContainer);
+begin
+	Collection := Value;
+end;
+
+{ TConnectionList }
+
+procedure TConnectionList.Add(Item: TConnectionList);
+begin
+	if not Assigned (FCollection.SearchForList (Item)) then begin
+		with TConItem(FCollection.Add) do
+			ConList := Item;
+	end;
+end;
+
+procedure TConnectionList.Clear;
+var
+	I: Integer;
+begin
+	for I := Count - 1 downto 0 do
+		DisconnectFrom (TConItem(FCollection.Items[I]).ConList);
+	FCollection.Clear;
+end;
+
+class procedure TConnectionList.ConnectLists(List1, List2: TConnectionList);
+begin
+	List1.Add (List2);
+	List2.Add (List1);
+end;
+
+procedure TConnectionList.ConnectTo(List: TConnectionList);
+begin
+	ConnectLists (Self, List);
+end;
+
+constructor TConnectionList.Create(AOwner: TPersistent);
+begin
+	inherited;
+	CreateCollection (TConItem);
+end;
+
+procedure TConnectionList.CreateCollection(AItemClass:
+	TCollectionItemClass);
+begin
+	FCollection := TConCollection.Create (Self, AItemClass);
+end;
+
+constructor TConnectionList.CreateSpecial(AOwner: TPersistent;
+	AItemClass: TCollectionItemClass);
+begin
+	inherited Create (AOwner);
+	CreateCollection (AItemClass);
+end;
+
+procedure TConnectionList.Delete(Item: TConnectionList);
+var
+	I: TConItem;
+begin
+	I := FCollection.SearchForList (Item);
+	if Assigned (I) then
+		I.Free;
+end;
+
+destructor TConnectionList.Destroy;
+begin
+	Clear;
+	FCollection.Free;
+	inherited;
+end;
+
+procedure TConnectionList.DisconnectFrom(List: TConnectionList);
+begin
+	DisconnectLists (Self, List);
+end;
+
+class procedure TConnectionList.DisconnectLists(List1, List2: TConnectionList);
+begin
+	List1.Delete (List2);
+	List2.Delete (List1);
+end;
+
+function TConnectionList.GetCount: Integer;
+begin
+	Result := FCollection.Count;
+end;
+
+function TConnectionList.IsConnectedTo(List: TConnectionList): Boolean;
+begin
+	Result := Assigned (Collection.SearchForList (List));
+end;
+
+procedure TConnectionList.PerformAction(Action: Integer; Obj: TObject);
+begin
+	if Assigned (FOnAction) then
+		FOnAction (Self, Action, Obj);
+end;
+
+procedure TConnectionList.PerformItemAction(Action: Integer; Obj: TObject);
+var
+	I: Integer;
+begin
+	for I := Count - 1 downto 0 do
+		TConItem(FCollection.Items[I]).ConList.PerformAction(Action, Obj);
+end;
+
+procedure TConnectionList.SetCollection(const Value: TConCollection);
+begin
+	FCollection.Assign (Value);
+end;
+
+{ TObjectContainer }
+
+procedure TObjectContainer.PerformItemAction(Action: Integer; Obj: TObject);
+var
+	I: Integer;
+begin
+	for I := Count - 1 downto 0 do
+		TContainerItem(Items[I]).PerformAction(Action, Obj);
+end;
+
+{ TOwnedPersistent }
+
+constructor TOwnedPersistent.Create(AOwner: TPersistent);
+begin
+	inherited Create;
+	SetOwner (AOwner);
+end;
+
+destructor TOwnedPersistent.Destroy;
+begin
+	SetOwner (nil);
+	inherited;
+end;
+
+function TOwnedPersistent.GetOwner: TPersistent;
+begin
+	Result := FOwner;
+end;
+
+procedure TOwnedPersistent.SetOwner(const Value: TPersistent);
+begin
+	FOwner := Value;
+end;
+
+{ TConItem }
+
+destructor TConItem.Destroy;
+begin
+	SetConList (nil);
+	inherited;
+end;
+
+function TConItem.GetOtherItem: TConItem;
+begin
+	if (not Assigned (FOtherItem)) and Assigned (ConList) then
+		FOtherItem := ConList.Collection.SearchForList ((Collection as TConCollection).Owner);
+	Result := FOtherItem;
+end;
+
+procedure TConItem.SetConList(const Value: TConnectionList);
+begin
+	if Assigned (FConList) and Assigned (FConList.FOnDisconnect) then
+		with TConCollection(Collection).GetOwner as TConnectionList do
+			FOnDisconnect (FConList, TConnectionList(TConCollection(Collection).GetOwner));
+	FConList := Value;
+	if Assigned (FConList) and Assigned (FConList.FOnConnect) then
+		with TConCollection(Collection).GetOwner as TConnectionList do
+			FOnConnect (FConList, TConnectionList(TConCollection(Collection).GetOwner));
+end;
+
+{ TConCollection }
+
+function TConCollection.GetNewOwner: TConnectionList;
+begin
+	Result := GetOwner as TConnectionList;
+end;
+
+function TConCollection.SearchForList(List: TConnectionList): TConItem;
+var
+	I:   Integer;
+	Res: TConItem;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do begin
+		Res := TConItem (Items [I]);
+		if Res.ConList = List then begin
+			Result := Res;
+			Break;
+		end;
+	end;
+end;
+
+{ TFastContainerItem }
+
+constructor TFastContainerItem.Create(Collection: TFastObjectContainer);
+begin
+	inherited Create;
+	SetCollection (Collection);
+end;
+
+destructor TFastContainerItem.Destroy;
+begin
+	SetCollection (nil);
+	inherited;
+end;
+
+function TFastContainerItem.GetIndex: Integer;
+begin
+	if Assigned (FCollection) then
+		Result := Collection.FItems.IndexOf (Self)
+	else
+		Result := -1;
+end;
+
+procedure TFastContainerItem.PerformAction(Action: Integer; Obj: TObject);
+begin
+	if Assigned (FOnAction) then
+		FOnAction (Self, Action, Obj);
+end;
+
+procedure TFastContainerItem.SetCollection(const Value: TFastObjectContainer);
+begin
+	if FCollection <> Value then begin
+		if Assigned (FCollection) then
+			FCollection.RemoveItem (Self);
+		if Assigned (Value) then
+			Value.InsertItem (Self);
+	end;
+end;
+
+procedure TFastContainerItem.SetIndex(const Value: Integer);
+var
+	CurIndex: Integer;
+begin
+	CurIndex := GetIndex;
+	if (CurIndex >= 0) and (CurIndex <> Value) then
+		FCollection.FItems.Move (CurIndex, Value);
+end;
+
+{ TFastObjectContainer }
+
+function TFastObjectContainer.Add: TFastContainerItem;
+begin
+	Result := FItemClass.Create (Self);
+end;
+
+procedure TFastObjectContainer.Clear;
+begin
+	while Count > 0 do
+		FItems.Last.Free;
+end;
+
+constructor TFastObjectContainer.Create(AOwner: TPersistent; ItemClass: TFastContainerItemClass);
+begin
+	inherited Create;
+	FItemClass := ItemClass;
+	FItems := TObjectList.Create (Self);
+	FOwner := AOwner;
+end;
+
+destructor TFastObjectContainer.Destroy;
+begin
+	if Assigned (FItems) then begin
+		Clear;
+		FItems.Free;
+	end;
+	inherited;
+end;
+
+function TFastObjectContainer.GetItem(Index: Integer): TFastContainerItem;
+begin
+	Result := TFastContainerItem (FItems [Index]);
+end;
+
+function TFastObjectContainer.Insert(Index: Integer): TFastContainerItem;
+begin
+	Result := Add;
+	Result.Index := Index;
+end;
+
+procedure TFastObjectContainer.InsertItem(Item: TFastContainerItem);
+begin
+	FItems.Add (Item);
+	Item.FCollection := Self;
+	Inc (FCount);
+end;
+
+procedure TFastObjectContainer.PerformItemAction(Action: Integer; Obj: TObject);
+var
+	I: Integer;
+begin
+	for I := Count - 1 downto 0 do
+		TContainerItem(Items[I]).PerformAction(Action, Obj);
+end;
+
+procedure TFastObjectContainer.RemoveItem(Item: TFastContainerItem);
+begin
+	FItems.Delete (Item);
+	Item.FCollection := nil;
+	Dec (FCount);
+end;
+
+end.

+ 895 - 0
tigcc/general/UtilsDos.pas

@@ -0,0 +1,895 @@
+unit UtilsDos;
+
+interface
+
+uses
+	WinProcs, WinTypes, SysUtils, Classes;
+
+type
+	TByteFile = file of Byte;
+	TDrive    = 'A'..'Z';
+	TDrives   = set of TDrive;
+
+function UCase (NormalChar: Char): Char;
+function LCase (NormalChar: Char): Char;
+function IsNormalChar (Ch: Char): Boolean;
+function ChangeText (var ChText: string; ToChange, ToInsert: string): Byte;
+function LastPos (const Substr, S: string): Integer;
+function PosEx (const Substr, S: string; StartPos: Integer; Backwards: Boolean = False): Integer;
+function FirstNonWhiteSpace (const S: string): Integer;
+
+function GetDriveDescription (Drive: TDrive): string;
+function DiskInDrive (Drive: TDrive): Boolean;
+function FileExistsWithCase (const FileName: string): Boolean;
+function DirExists (const Directory: string): Boolean;
+function DirExistsWithCase (const Directory: string): Boolean;
+function GetFileSize (const FileName: string): Integer;
+function GetSubDir (const Directory: string): string;
+function GetHigherDir (const Directory: string): string;
+function GetLowerName (const N: string): string;
+function SizeToStr (Size: Int64): string;
+function AttrToStr (Attr: Integer): string;
+procedure CreatePath (const Directory: string);
+procedure CreatePathFor (const FileName: string);
+procedure RemovePath (const Directory: string; const StopAt: string = '');
+procedure RemovePathFor (const FileName: string; const StopAt: string = '');
+procedure DelTree (const Directory: string);
+procedure DelAllFiles (const Directory: string);
+
+procedure PCSpeakerPlay (Frequency: Word);
+procedure PCSpeakerStop;
+
+procedure SetDate (a: Word; m, d: Byte);
+procedure SetTime (h, m, s, hs: Byte);
+
+procedure WrCStr (var F: TByteFile; Str: string);
+procedure WrPStr (var F: TByteFile; Str: string; Len: Byte);
+procedure WrVStr (var F: TByteFile; Str: string);
+procedure WrSInt (var F: TByteFile; Value: ShortInt);
+procedure WrByte (var F: TByteFile; Value: Byte);
+procedure WrNInt (var F: TByteFile; Value: SmallInt);
+procedure WrWord (var F: TByteFile; Value: Word);
+procedure RdCStr (var F: TByteFile; var Str: string; Len: Byte);
+procedure RdPStr (var F: TByteFile; var Str: string; Len: Byte);
+procedure RdVStr (var F: TByteFile; var Str: string);
+procedure RdSInt (var F: TByteFile; var Value: ShortInt);
+procedure RdByte (var F: TByteFile; var Value: Byte);
+procedure RdNInt (var F: TByteFile; var Value: SmallInt);
+procedure RdWord (var F: TByteFile; var Value: Word);
+
+type
+	TFileAttribute = (atDirectory, atArchive, atReadOnly, atHidden, atSystem);
+	// atDirectory only for internal use and property request
+	TFileAttributes = set of TFileAttribute;
+
+const
+	atStd: TFileAttributes = [atArchive, atReadOnly];
+	atAll: TFileAttributes = [atArchive, atReadOnly, atHidden, atSystem];
+
+type
+	TFileReferences = class;
+
+	TFileReference = class(TPersistent)
+	private
+		FOwner: TFileReferences;
+		FSearchRec: TSearchRec;
+		function GetCreationTime: TDateTime;
+		function GetFileAttr: TFileAttributes;
+		function GetFileName: string;
+		function GetFileSize: Integer;
+		function GetFullName: string;
+		function GetFullShortName: string;
+		function GetLastAccessTime: TDateTime;
+		function GetModificationTime: TDateTime;
+		function GetShortFileName: string;
+	public
+	published
+		property Owner: TFileReferences read FOwner;
+		property RecData: TSearchRec read FSearchRec;
+		property FullName: string read GetFullName;
+		property FileName: string read GetFileName;
+		property FullShortName: string read GetFullShortName;
+		property ShortFileName: string read GetShortFileName;
+		property CreationTime: TDateTime read GetCreationTime;
+		property ModificationTime: TDateTime read GetModificationTime;
+		property LastAccessTime: TDateTime read GetLastAccessTime;
+		property FileSize: Integer read GetFileSize;
+		property FileAttr: TFileAttributes read GetFileAttr;
+	end;
+
+	TFileReferences = class(TPersistent)
+	private
+		FList: TList;
+		FDirectory: string;
+		FWildCard: string;
+		FSearchAttr: TFileAttributes;
+		FSearchTime: TDateTime;
+		function GetItem(ItemIndex: Integer): TFileReference;
+		function GetCount: Integer;
+	public
+		constructor Create;
+		destructor Destroy; override;
+		function Add(const F: TSearchRec): Integer; virtual;
+		procedure Delete(Index: Integer); virtual;
+		procedure Clear;
+		procedure SearchForFiles(FileName: string; FileAttr: TFileAttributes);
+		procedure SearchForDirs(const ParentDir: string; FileAttr: TFileAttributes);
+		procedure CopyToStrings(const S: TStrings);
+		procedure CopyFullNamesToStrings(const S: TStrings);
+		property Items[ItemIndex: Integer]: TFileReference read GetItem;
+		property Count: Integer read GetCount;
+	published
+		property Directory: string read FDirectory;
+		property WildCard: string read FWildCard;
+		property SearchAttr: TFileAttributes read FSearchAttr;
+		property SearchTime: TDateTime read FSearchTime;
+	end;
+
+function WinFileTimeToDateTime(WinFileTime: TFileTime): TDateTime;
+function WinFileAttrToFileAttr(WinFileAttr: Integer): TFileAttributes;
+function FileAttrToWinFileAttr(FileAttr: TFileAttributes): Integer;
+
+procedure AddBackslash(var Dir: string);
+function WithBackslash(const Dir: string): string;
+function WithoutBackslash(const Dir: string): string;
+function WithoutExt(const FileName: string): string;
+
+implementation
+
+function UCase;
+begin
+	Result := UpCase (NormalChar);
+	case Result of
+		'ä': Result := 'Ä';
+		'ö': Result := 'Ö';
+		'ü': Result := 'Ü';
+	end;
+end;
+
+function LCase;
+begin
+	Result := LowerCase (NormalChar) [1];
+	case Result of
+		'Ä': Result := 'ä';
+		'Ö': Result := 'ö';
+		'Ü': Result := 'ü';
+	end;
+end;
+
+function IsNormalChar;
+begin
+	Result := UCase (Ch) <> LCase (Ch);
+end;
+
+function LastPos;
+var
+	I: Integer;
+begin
+	Result := 0;
+	for I := Length (S) - Length (Substr) + 1 downto 1 do
+		if Copy (S, I, Length (Substr)) = Substr then begin
+			Result := I;
+			Break;
+		end;
+end;
+
+function PosEx;
+var
+	I: Integer;
+begin
+	Result := 0;
+	if Backwards then begin
+		for I := StartPos downto 1 do
+			if Copy (S, I, Length (Substr)) = Substr then begin
+				Result := I;
+				Break;
+			end;
+	end else begin
+		for I := StartPos to Length (S) - Length (Substr) + 1 do
+			if Copy (S, I, Length (Substr)) = Substr then begin
+				Result := I;
+				Break;
+			end;
+	end;
+end;
+
+function FirstNonWhiteSpace;
+var
+	I: Integer;
+begin
+	Result := Length (S) + 1;
+	for I := 1 to Length (S) do
+		if not (S [I] in [' ', #9]) then begin
+			Result := I;
+			Break;
+		end;
+end;
+
+function GetDriveDescription;
+var
+	F: Text;
+	R,
+	N: array [0..255] of Char;
+	V: DWord;
+begin
+	Result := '';
+	if FileExists (Drive + ':\DiskID.clk') then begin
+		AssignFile (F, Drive + ':\DiskID.clk');
+		Reset (F);
+		ReadLn (F, Result);
+		CloseFile (F);
+	end else begin
+		StrPCopy (R, Drive + ':\');
+		if GetVolumeInformation (R, N, 255, nil, V, V, nil,	0) then
+			Result := StrPas (N);
+	end;
+	if Result = '' then
+		Result := Drive + ':\';
+	Result := GetLowerName (Result);
+end;
+
+function DiskInDrive;
+var
+	V: DWord;
+begin
+	Result := GetDiskFreeSpace (PChar (Drive + ':\'), V, V, V, V);
+end;
+
+procedure CreatePath;
+var
+	SeedPath: string;
+	CurPath: string;
+begin
+	SeedPath := WithBackslash (Directory);
+	CurPath := '';
+	while Pos ('\', SeedPath) > 0 do begin
+		CurPath := CurPath + Copy (SeedPath, 1, Pos ('\', SeedPath));
+		Delete (SeedPath, 1, Pos ('\', SeedPath));
+		if Length (CurPath) > 3 then
+			if not DirExists (CurPath) then try
+				MkDir (CurPath);
+			except end;
+	end;
+end;
+
+procedure CreatePathFor;
+begin
+	CreatePath (ExtractFilePath (FileName));
+end;
+
+procedure RemovePath;
+var
+	Dir: string;
+	S: TSearchRec;
+	Found: Boolean;
+begin
+	Dir := WithBackslash (Directory);
+	if (Length (Dir) > 3) and (Dir <> WithBackslash (StopAt)) and DirExists (Dir) then begin
+		Found := False;
+		if FindFirst (Dir + '*', faAnyFile, S) = 0 then begin
+			repeat
+				if (S.Name <> '.') and (S.Name <> '..') then
+					Found := True;
+			until (FindNext (S) <> 0) or Found;
+		end;
+		FindClose (S);
+		if not Found then try
+			RmDir (Dir);
+			RemovePath (GetHigherDir (Directory), StopAt);
+		except end;
+	end;
+end;
+
+procedure RemovePathFor;
+begin
+	RemovePath (ExtractFilePath (FileName), StopAt);
+end;
+
+procedure DelTree;
+var
+	CurDelDir: string;
+begin
+	CurDelDir := WithBackslash (Directory);
+	repeat
+		while GetSubDir (CurDelDir) <> '' do begin
+			CurDelDir := CurDelDir + GetSubDir
+				(CurDelDir) + '\';
+		end;
+		DelAllFiles (CurDelDir);
+		if Length (CurDelDir) < 4 then
+			RmDir (CurDelDir)
+		else
+			RmDir (Copy (CurDelDir, 1, Length (CurDelDir) - 1));
+		CurDelDir := GetHigherDir (CurDelDir);
+	until CurDelDir = GetHigherDir (Directory);
+end;
+
+function FileExistsWithCase;
+var
+	S: TSearchRec;
+begin
+	Result := (FindFirst (FileName, faAnyFile, S) = 0);
+	if Result and (S.Name <> ExtractFileName (FileName)) then
+		Result := False;
+	FindClose (S);
+end;
+
+function DirExists;
+var
+	S: TSearchRec;
+begin
+	Result := (FindFirst (WithoutBackslash (Directory), faDirectory or faHidden or faSysFile, S) = 0);
+	FindClose (S);
+end;
+
+function DirExistsWithCase;
+var
+	S: TSearchRec;
+begin
+	Result := (FindFirst (WithoutBackslash (Directory), faDirectory, S) = 0);
+	if Result and (S.Name <> ExtractFileName (WithoutBackslash (Directory))) then
+		Result := False;
+	FindClose (S);
+end;
+
+function GetFileSize;
+var
+	S: TSearchRec;
+begin
+	if FindFirst (FileName, faAnyFile, S) = 0 then
+		Result := S.Size
+	else
+		Result := 0;
+	FindClose (S);
+end;
+
+function GetSubDir;
+var
+	SR1:  TSearchRec;
+	GoOn: Boolean;
+begin
+	GoOn := True;
+	if FindFirst (Directory + '*.*', $10, SR1) = 0 then begin
+		while GoOn and (((SR1.Attr and $10) = 0) or (SR1.Name = '.') or (SR1.Name = '..')) do begin
+			if FindNext (SR1) <> 0 then begin
+				SR1.Name := '';
+				GoOn := False;
+			end;
+		end;
+		GetSubDir := SR1.Name
+	end else
+		GetSubDir := '';
+	FindClose (SR1);
+end;
+
+function GetHigherDir;
+begin
+	Result := ExtractFilePath (WithoutBackslash (Directory));
+end;
+
+procedure DelAllFiles;
+var
+	SR1: TSearchRec;
+begin
+	if FindFirst (Directory + '*.*', $20, SR1) = 0 then begin
+		SysUtils.DeleteFile (Directory + SR1.Name);
+		while FindNext (SR1) = 0 do
+			SysUtils.DeleteFile (Directory + SR1.Name);
+	end;
+	FindClose (SR1);
+end;
+
+function GetLowerName;
+var
+	I: Integer;
+begin
+	Result := N;
+	if (Length (Result) > 0) and ((Result = UpperCase (Result)) or (Result = LowerCase (Result))) then begin
+		Result := UpperCase (Result);
+		for I := 2 to Length (Result) do begin
+			if IsNormalChar (Result [I-1]) then
+				Result [I] := LCase (Result [I]);
+		end;
+	end;
+end;
+
+function SizeToStr;
+var
+	Sz: Real;
+	M:  Byte;
+begin
+	M := 0;
+	Sz := Size;
+	while Sz >= 1000 do begin
+		Sz := Sz / 1000;
+		Inc (M);
+	end;
+	Result := FloatToStr (Sz);
+	if Length (Result) > 4 then
+		Result := Copy (Result, 1, 4);
+	if Result [Length (Result)] = DecimalSeparator then
+		Delete (Result, Length (Result), 1);
+	case M of
+		0: Result := Result + ' B';
+		1: Result := Result + ' KB';
+		2: Result := Result + ' MB';
+		3: Result := Result + ' GB';
+		4: Result := Result + ' TB';
+		else Result := Result + '...';
+	end;
+end;
+
+function AttrToStr;
+begin
+	Result := '';
+	if (Attr and faArchive)  <> 0 then Result := Result + 'A';
+	if (Attr and faReadOnly) <> 0 then Result := Result + 'R';
+	if (Attr and faHidden)   <> 0 then Result := Result + 'H';
+	if (Attr and faSysFile)  <> 0 then Result := Result + 'S';
+end;
+
+function ChangeText;
+var
+	TxtPs: Byte;
+begin
+	TxtPs := 0;
+	while Pos (ToChange, ChText) <> 0 do begin
+		TxtPs := Pos (ToChange, ChText);
+		Delete (Chtext, TxtPs, Length (ToChange));
+		Insert (ToInsert, ChText, TxtPs);
+	end;
+	ChangeText := TxtPs;
+end;
+
+procedure PCSpeakerPlay (Frequency: Word); assembler;
+asm
+	Mov  BX,  Frequency
+	Mov  AX,  $34DD
+	Mov  DX,  $0012
+	Cmp  DX,  BX
+	Jnb  @EndOfProc
+	Div  BX
+	Mov  BX,  AX
+	In   AL,  $61
+	Test AL,  $03
+	Jne  @NearlyEndOfProc
+	Or   AL,  $03
+	Out  $61, AL
+	Mov  AL,  $B6
+	Out  $43, AL
+@NearlyEndOfProc:
+	Mov  AL,  BL
+	Out  $42, AL
+	Mov  AL,  BH
+	Out  $42, AL
+@EndOfProc:
+end;
+
+procedure PCSpeakerStop; assembler;
+asm
+	In   AL,  $61
+	And  AL,  $FC
+	Out  $61, AL
+end;
+
+procedure SetDate; assembler;
+asm
+	Mov  CX,  a
+	Mov  DH,  m
+	Mov  DL,  d
+	Mov  AH,  $2B
+	Int  $21
+end;
+
+procedure SetTime; assembler;
+asm
+	Mov  CH,  h
+	Mov  CL,  m
+	Mov  DH,  s
+	Mov  DL,  hs
+	Mov  AH,  $2D
+	Int  $21
+end;
+
+procedure WrCStr;
+var
+	VLp1,
+	VHlp: Byte;
+begin
+	for VLp1 := 1 to Length (Str) do begin
+		VHlp := Ord (Str [VLp1]);
+		Write (F, VHlp);
+	end;
+end;
+
+procedure WrPStr;
+var
+	VLp1,
+	VHlp,
+	VHp2: Byte;
+begin
+	VHlp := Length (Str);
+	if VHlp > Len then VHlp := Len;
+	Write (F, VHlp);
+	for VLp1 := 1 to VHlp do begin
+		VHp2 := Ord (Str [VLp1]);
+		Write (F, VHp2);
+	end;
+	VHp2 := 0;
+	for VLp1 := VHlp + 1 to Len do Write (F, VHp2);
+end;
+
+procedure WrVStr;
+var
+	VLp1,
+	VHlp: Byte;
+begin
+	VHlp := Length (Str);
+	Write (F, VHlp);
+	for VLp1 := 1 to VHlp do begin
+		VHlp := Ord (Str [VLp1]);
+		Write (F, VHlp);
+	end;
+end;
+
+procedure WrSInt;
+var
+	VHlp: Byte;
+begin
+	VHlp := Byte (Value);
+	Write (F, VHlp);
+end;
+
+procedure WrByte;
+var
+	VHlp: Byte;
+begin
+	VHlp := Value;
+	Write (F, VHlp);
+end;
+
+procedure WrNInt;
+var
+	VHlp: Byte;
+begin
+	VHlp := Hi (Word (Value));
+	Write (F, VHlp);
+	VHlp := Lo (Word (Value));
+	Write (F, VHlp);
+end;
+
+procedure WrWord;
+var
+	VHlp: Byte;
+begin
+	VHlp := Hi (Value);
+	Write (F, VHlp);
+	VHlp := Lo (Value);
+	Write (F, VHlp);
+end;
+
+procedure RdCStr;
+var
+	VLp1,
+	VHlp: Byte;
+begin
+	Str := '';
+	for VLp1 := 1 to Len do begin
+		Read (F, VHlp);
+		Str := Str + Chr (VHlp);
+	end;
+end;
+
+procedure RdPStr;
+var
+	FPos,
+	VLp1,
+	VHlp: Byte;
+begin
+	FPos := FilePos (F);
+	Str := '';
+	Read (F, VHlp);
+	for VLp1 := 1 to VHlp do begin
+		Read (F, VHlp);
+		Str := Str + Chr (VHlp);
+	end;
+	Seek (F, FPos + Len + 1);
+end;
+
+procedure RdVStr;
+var
+	VLp1,
+	VHlp: Byte;
+begin
+	Str := '';
+	Read (F, VHlp);
+	for VLp1 := 1 to VHlp do begin
+		Read (F, VHlp);
+		Str := Str + Chr (VHlp);
+	end;
+end;
+
+procedure RdSInt;
+var
+	VHlp: Byte;
+begin
+	Read (F, VHlp);
+	Value := ShortInt (VHlp);
+end;
+
+procedure RdByte;
+begin
+	Read (F, Value);
+end;
+
+procedure RdNInt;
+var
+	VHlp1: Byte;
+	VHlp2: Word;
+begin
+	Read (F, VHlp1);
+	VHlp2 := VHlp1 * 256;
+	Read (F, VHlp1);
+	Inc (VHlp2, VHlp1);
+	Value := SmallInt (VHlp2);
+end;
+
+procedure RdWord;
+var
+	VHlp: Byte;
+begin
+	Read (F, VHlp);
+	Value := VHlp * 256;
+	Read (F, VHlp);
+	Inc (Value, VHlp);
+end;
+
+function WinFileTimeToDateTime(WinFileTime: TFileTime): TDateTime;
+var
+	Time: Integer;
+	LocalFileTime: TFileTime;
+begin
+	FileTimeToLocalFileTime(WinFileTime, LocalFileTime);
+	FileTimeToDosDateTime(LocalFileTime, LongRec(Time).Hi, LongRec(Time).Lo);
+	Result := FileDateToDateTime (Time);
+end;
+
+function WinFileAttrToFileAttr(WinFileAttr: Integer): TFileAttributes;
+begin
+	Result := [];
+	if (WinFileAttr and faDirectory) <> 0 then
+		Include (Result, atDirectory);
+	if (WinFileAttr and faArchive) <> 0 then
+		Include (Result, atArchive);
+	if (WinFileAttr and faReadOnly) <> 0 then
+		Include (Result, atReadOnly);
+	if (WinFileAttr and faHidden) <> 0 then
+		Include (Result, atHidden);
+	if (WinFileAttr and faSysFile) <> 0 then
+		Include (Result, atSystem);
+end;
+
+function FileAttrToWinFileAttr(FileAttr: TFileAttributes): Integer;
+begin
+	Result := 0;
+	if atDirectory in FileAttr then
+		Result := Result or faDirectory;
+	if atArchive in FileAttr then
+		Result := Result or faArchive;
+	if atReadOnly in FileAttr then
+		Result := Result or faReadOnly;
+	if atHidden in FileAttr then
+		Result := Result or faHidden;
+	if atSystem in FileAttr then
+		Result := Result or faSysFile;
+end;
+
+procedure AddBackslash(var Dir: string);
+begin
+	if (Length (Dir) > 0) and (Dir [Length (Dir)] <> '\') then
+		Dir := Dir + '\';
+end;
+
+function WithBackslash(const Dir: string): string;
+begin
+	if (Length (Dir) > 0) and (Dir [Length (Dir)] <> '\') then
+		Result := Dir + '\'
+	else
+		Result := Dir;
+end;
+
+function WithoutBackslash(const Dir: string): string;
+begin
+	if (Length (Dir) > 0) and (Length (Dir) > 3) and (Dir [Length (Dir)] = '\') then
+		Result := Copy (Dir, 1, Length (Dir) - 1)
+	else
+		Result := Dir;
+end;
+
+function WithoutExt(const FileName: string): string;
+begin
+	Result := ChangeFileExt (FileName, '');
+end;
+
+{ TFileReference }
+
+function TFileReference.GetCreationTime: TDateTime;
+begin
+	Result := WinFileTimeToDateTime (FSearchRec.FindData.ftCreationTime);
+end;
+
+function TFileReference.GetFileAttr: TFileAttributes;
+begin
+	Result := WinFileAttrToFileAttr (FSearchRec.Attr);
+end;
+
+function TFileReference.GetFileName: string;
+begin
+	Result := FSearchRec.Name;
+end;
+
+function TFileReference.GetFileSize: Integer;
+begin
+	Result := FSearchRec.Size;
+end;
+
+function TFileReference.GetFullName: string;
+begin
+	Result := FOwner.Directory + FSearchRec.Name;
+end;
+
+function TFileReference.GetFullShortName: string;
+var
+	TmpDir: string;
+	F: TSearchRec;
+begin
+	Result := ShortFileName;
+	TmpDir := FOwner.Directory;
+	Delete (TmpDir, Length (TmpDir), 1);
+	while Length (TmpDir) > 2 do begin
+		if FindFirst (TmpDir, faDirectory or faReadOnly or faHidden or faSysFile or faArchive, F) = 0 then begin
+			if F.FindData.cAlternateFileName = '' then
+				Result := F.Name + '\' + Result
+			else
+				Result := F.FindData.cAlternateFileName + '\' + Result
+		end else
+			Result := ExtractFileName (TmpDir) + '\' + Result;
+		FindClose (F);
+		Delete (TmpDir, LastPos ('\', TmpDir), Length (TmpDir));
+	end;
+	Result := TmpDir + '\' + Result;
+end;
+
+function TFileReference.GetLastAccessTime: TDateTime;
+begin
+	Result := WinFileTimeToDateTime (FSearchRec.FindData.ftLastAccessTime);
+end;
+
+function TFileReference.GetModificationTime: TDateTime;
+begin
+	Result := WinFileTimeToDateTime (FSearchRec.FindData.ftLastWriteTime);
+end;
+
+function TFileReference.GetShortFileName: string;
+begin
+	Result := FSearchRec.FindData.cAlternateFileName;
+	if Result = '' then
+		Result := FSearchRec.Name;
+end;
+
+{ TFileReferences }
+
+function TFileReferences.Add(const F: TSearchRec): Integer;
+var
+	R: TFileReference;
+begin
+	R := TFileReference.Create;
+	with R do begin
+		FOwner := Self;
+		FSearchRec := F;
+	end;
+	Result := FList.Add (Pointer (R));
+end;
+
+procedure TFileReferences.Clear;
+begin
+	while Count > 0 do
+		Delete (Count - 1);
+end;
+
+procedure TFileReferences.CopyFullNamesToStrings(const S: TStrings);
+var
+	I: Integer;
+begin
+	S.BeginUpdate;
+	for I := 0 to Count - 1 do
+		S.AddObject (Items[I].FullName, Items [I]);
+	S.EndUpdate;
+end;
+
+procedure TFileReferences.CopyToStrings(const S: TStrings);
+var
+	I,
+	P: Integer;
+	N: string;
+begin
+	S.BeginUpdate;
+	for I := 0 to Count - 1 do begin
+		N := Items[I].FileName;
+		P := LastPos ('.', N);
+		if P < 1 then
+			P := Length (N)
+		else
+			Dec (P);
+		S.AddObject (GetLowerName (Copy (N, 1, P)), Items [I]);
+	end;
+	S.EndUpdate;
+end;
+
+constructor TFileReferences.Create;
+begin
+	inherited;
+	FList := TList.Create;
+end;
+
+procedure TFileReferences.Delete(Index: Integer);
+begin
+	with FList do begin
+		TFileReference(Items[Index]).Free;
+		Delete (Index);
+	end;
+end;
+
+destructor TFileReferences.Destroy;
+begin
+	inherited;
+	Clear;
+	FList.Free;
+end;
+
+function TFileReferences.GetCount: Integer;
+begin
+	Result := FList.Count;
+end;
+
+function TFileReferences.GetItem(ItemIndex: Integer): TFileReference;
+begin
+	Result := TFileReference (FList.Items [ItemIndex]);
+end;
+
+procedure TFileReferences.SearchForDirs(const ParentDir: string;
+	FileAttr: TFileAttributes);
+var
+	Mask: string;
+begin
+	if Length (ParentDir) > 0 then
+		Mask := WithBackslash (ParentDir)
+	else
+		Mask := '*.*';
+	SearchForFiles (Mask, FileAttr + [atDirectory]);
+end;
+
+procedure TFileReferences.SearchForFiles(FileName: string;
+	FileAttr: TFileAttributes);
+var
+	F: TSearchRec;
+	R: Integer;
+begin
+	Clear;
+	if (FileName = '') or (FileName [Length (FileName)] = '\') then
+		FileName := FileName + '*.*';
+	FileName := ExpandFileName (FileName);
+	FDirectory := ExtractFilePath (FileName);
+	FWildCard := ExtractFileName (FileName);
+	FSearchAttr := FileAttr;
+	R := FindFirst (FileName, FileAttrToWinFileAttr (FileAttr), F);
+	while R = 0 do begin
+		if (not ((atDirectory in FileAttr) and ((faDirectory and F.Attr) = 0))) and (F.Name [1] <> '.') and ((WinFileAttrToFileAttr (F.Attr) - FileAttr) = []) then
+			Add (F);
+		R := FindNext (F);
+	end;
+	FindClose (F);
+	FSearchTime := Now;
+end;
+
+end.

+ 30 - 0
tigcc/general/UtilsSys.pas

@@ -0,0 +1,30 @@
+unit UtilsSys;
+
+interface
+
+uses
+	Windows, SysUtils, Classes;
+
+function LastPos (const Substr, S: string): Integer;
+
+var
+	AppLocationDir: string; // the directory where the program was started from, with a '\' at the end
+
+implementation
+
+function LastPos;
+var
+	I: Integer;
+begin
+	for I := Length (S) - Length (Substr) + 1 downto 1 do begin
+		if Copy (S, I, Length (SubStr)) = Substr then begin
+			Result := I;
+			Exit;
+		end;
+	end;
+	Result := 0;
+end;
+
+initialization
+	AppLocationDir := ExtractFilePath (ParamStr (0));
+end.

+ 114 - 0
tigcc/general/UtilsWin.pas

@@ -0,0 +1,114 @@
+unit UtilsWin;
+
+interface
+
+uses
+	Windows;
+
+type
+	TMessageButtons = (mbOK, mbOKCancel, mbYesNo, mbYesNoCancel, mbRetryCancel, mbAbortRetryIgnore);
+	TMessageIcon = (miNone, miAsterisk, miInformation, miQuestion, miExclamation, miWarning, miHand, miStop, miError);
+	TMessageModalState = (msDefault, msApplModal, msSystemModal, msTaskModal);
+	TDefaultMessageType = (mtDefault, mtInformation, mtQuestion, mtWarning, mtProgramError, mtDeviceError);
+
+function ShowMessageBox(const Content, Title: string; Buttons: TMessageButtons = mbOK; Icon: TMessageIcon = miNone; ModalState: TMessageModalState = msDefault; DisplayHelp: Boolean = False; DefaultButton: Integer = 0; Flags: Integer = 0): Integer;
+function ShowDefaultMessageBox(const Content, Title: string; MessageType: TDefaultMessageType = mtDefault; Critical: Boolean = False; DisplayHelp: Boolean = False; DefaultButton: Integer = 0): Integer;
+
+function CompressMessageFlags(Buttons: TMessageButtons; Icon: TMessageIcon; ModalState: TMessageModalState; DisplayHelp: Boolean; DefaultButton: Integer): Integer;
+
+implementation
+
+function ShowMessageBox;
+begin
+	Result := MessageBox (GetActiveWindow, PChar (Content), PChar (Title), Flags or CompressMessageFlags (Buttons, Icon, ModalState, DisplayHelp, DefaultButton));
+end;
+
+function ShowDefaultMessageBox;
+var
+	Buttons: TMessageButtons;
+	Icon:    TMessageIcon;
+begin
+	case MessageType of
+		mtInformation: begin
+			if Critical then
+				Buttons := mbOKCancel
+			else
+				Buttons := mbOK;
+			Icon := miInformation;
+		end;
+		mtQuestion: begin
+			if Critical then
+				Buttons := mbYesNoCancel
+			else
+				Buttons := mbYesNo;
+			Icon := miQuestion;
+		end;
+		mtWarning: begin
+			if Critical then
+				Buttons := mbOKCancel
+			else
+				Buttons := mbOK;
+			Icon := miWarning;
+		end;
+		mtProgramError: begin
+			if Critical then
+				Buttons := mbOKCancel
+			else
+				Buttons := mbOK;
+			Icon := miError;
+		end;
+		mtDeviceError: begin
+			if Critical then
+				Buttons := mbRetryCancel
+			else
+				Buttons := mbAbortRetryIgnore;
+			Icon := miError;
+		end;
+		else begin
+			if Critical then
+				Buttons := mbOKCancel
+			else
+				Buttons := mbOK;
+			Icon := miNone;
+		end;
+	end;
+	Result := ShowMessageBox (Content, Title, Buttons, Icon, msDefault, DisplayHelp, DefaultButton, 0);
+end;
+
+function CompressMessageFlags;
+begin
+	case Buttons of
+		mbOK:               Result := mb_OK;
+		mbOKCancel:         Result := mb_OKCancel;
+		mbYesNo:            Result := mb_YesNo;
+		mbYesNoCancel:      Result := mb_YesNoCancel;
+		mbRetryCancel:      Result := mb_RetryCancel;
+		mbAbortRetryIgnore: Result := mb_AbortRetryIgnore;
+		else                Result := 0;
+	end;
+	case Icon of
+		miAsterisk:    Result := Result or mb_IconAsterisk;
+		miInformation: Result := Result or mb_IconInformation;
+		miQuestion:    Result := Result or mb_IconQuestion;
+		miExclamation: Result := Result or mb_IconExclamation;
+		miWarning:     Result := Result or mb_IconWarning;
+		miHand:        Result := Result or mb_IconHand;
+		miStop:        Result := Result or mb_IconStop;
+		miError:       Result := Result or mb_IconError;
+	end;
+	case ModalState of
+		msApplModal:   Result := Result or mb_ApplModal;
+		msSystemModal: Result := Result or mb_SystemModal;
+		msTaskModal:   Result := Result or mb_TaskModal;
+	end;
+	if DisplayHelp then
+		Result := Result or mb_Help;
+	case DefaultButton of
+		1: Result := Result or mb_DefButton1;
+		2: Result := Result or mb_DefButton2;
+		3: Result := Result or mb_DefButton3;
+		4: Result := Result or mb_DefButton4;
+	end;
+end;
+
+end.

+ 340 - 0
tigcc/hsf2rc/License.txt

@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

+ 8 - 0
tigcc/hsf2rc/NotDefinedRom_calls

@@ -0,0 +1,8 @@
+;Some rom_calls are not defined in TIGCC documentation because they are AMS1 specific
+;or they are implemented as a macro or a function
+NoCallBack $31
+caddcert $126
+cgetvernum $131
+EM_writeToExtMem $168
+OSVRegisterTimer $284
+OSVFreeTimer $285

+ 19 - 0
tigcc/hsf2rc/db92_alias

@@ -0,0 +1,19 @@
+163 y
+162 n
+1162 y
+963 y
+412 y
+589 y
+591 n
+588 n
+592 n
+594 n
+230 n
+767 n
+768 n
+769 n
+770 n
+771 n
+772 n
+773 n
+102 y

+ 206 - 0
tigcc/hsf2rc/doorsos.h.end

@@ -0,0 +1,206 @@
+
+doorsos::ScreenClear equ _ROM_CALL_19E
+doorsos::DrawStrXY equ _ROM_CALL_1A9
+doorsos::ArchiveErase equ _ROM_CALL_16A+$10
+doorsos::ArchiveWrite equ _ROM_CALL_171
+doorsos::bcdadd equ _ROM_CALL_B6
+doorsos::bcdcmp equ _ROM_CALL_BB
+doorsos::bcddiv equ _ROM_CALL_B9
+doorsos::bcdbcd equ _ROM_CALL_BD
+doorsos::bcdmul equ _ROM_CALL_B8
+doorsos::bcdneg equ _ROM_CALL_BA
+doorsos::bcdsub equ _ROM_CALL_B7
+doorsos::bcdlong equ _ROM_CALL_BC
+
+CALCULATOR		equ	_RAM_CALL_000
+HW_VERSION		equ	CALCULATOR+1
+LCD_WIDTH		equ	_RAM_CALL_001
+LCD_HEIGHT		equ	_RAM_CALL_002
+doorsos::ROM_base	equ	_RAM_CALL_003
+LCD_LINE_BYTES	equ	_RAM_CALL_004
+KEY_LEFT		equ	_RAM_CALL_005
+KEY_RIGHT		equ	_RAM_CALL_006
+KEY_UP			equ	_RAM_CALL_007
+KEY_DOWN		equ	_RAM_CALL_008
+KEY_UPRIGHT		equ	_RAM_CALL_009
+KEY_DOWNLEFT		equ	_RAM_CALL_00A
+KEY_DIAMOND		equ	_RAM_CALL_00B
+LCD_SIZE		equ	_RAM_CALL_00C
+KEY_SHIFT		equ	_RAM_CALL_00D
+doorsos::font_medium	equ	_RAM_CALL_00E
+ReturnValue		equ	_RAM_CALL_00F
+doorsos::kb_globals	equ	_RAM_CALL_010
+doorsos::Heap		equ	_RAM_CALL_011
+doorsos::FolderListHandle equ	_RAM_CALL_012
+doorsos::MainHandle	equ	_RAM_CALL_013
+ROM_VERSION		equ	_RAM_CALL_014
+
+doorsos::font_small	equ	doorsos::font_medium+$800
+doorsos::font_large	equ	doorsos::font_medium+$E00
+
+LCD_MEM equ $4c00
+doorsos::main_lcd equ LCD_MEM
+doorsos::globals equ $4c00
+doorsos::OSOnBreak	equ	doorsos::globals+$F02
+
+
+doorsos::MaxHandles	equ	doorsos::Heap-$16
+doorsos::TopHeap   	equ     doorsos::Heap-$C
+doorsos::FirstFreeByte	equ	doorsos::Heap-$14
+
+doorsos::kb_vars	equ 	doorsos::kb_globals
+
+KEY_PRESSED_FLAG	equ	doorsos::kb_globals+$1c
+GETKEY_CODE		equ	doorsos::kb_globals+$1e
+
+APD_INIT	equ	LCD_MEM+$F10
+APD_TIMER	equ	LCD_MEM+$F14
+APD_FLAG	equ	LCD_MEM+$F42
+
+doorsos::SYM_ENTRY.name equ 0
+doorsos::SYM_ENTRY.flags equ 8
+doorsos::SYM_ENTRY.hVal equ $c
+doorsos::NULL equ 0
+doorsos::H_NULL equ 0
+doorsos::RAND_MAX equ $7fff
+ACTIVITY_IDLE equ 0
+ACTIVITY_BUSY equ 1
+ACTIVITY_PAUSED equ 2
+doorsos::ER_STOP equ 2
+doorsos::ER_DIMENSION equ 230
+doorsos::ER_MEMORY equ 670
+doorsos::ER_MEMORY_DML equ 810
+doorsos::UNDEFINED_TAG equ $2a
+doorsos::LIST_TAG equ $d9
+doorsos::MATRIX_TAG equ $db
+doorsos::END_TAG equ $e5
+CALC_TI89 equ 0
+CALC_TI92PLUS equ 1
+
+ROM_CALL macro
+ move.l ($C8),a4
+ add.l #\1*4,a4
+ move.l (a4),a4
+ jsr (a4)
+ endm
+
+EXTRA_RAM_TABLE macro
+_extraram:
+    xdef _extraram
+    endm
+
+EXTRA_RAM_ADDR macro
+    dc.w \3
+    dc.w \4
+\2 equ _extraramaddr@\1
+    endm
+
+doorsos::DEREF     macro   ; Dn,An
+	lsl.w	#2,\1
+        move.l  doorsos::Heap,\2
+	move.l	0(\2,\1.w),\2
+		endm
+
+SetFont	macro
+	move.w	\1,-(a7)
+	jsr	doorsos::FontSetSys
+	addq.l	#2,a7
+		endm
+
+WriteStr	macro	;x,y,col,str
+	move.w	\3,-(a7)
+	pea	\4(pc)
+	move.w	\2,-(a7)
+	move.w	\1,-(a7)
+	jsr	doorsos::DrawStrXY
+	lea	10(a7),a7
+                endm
+
+WriteStrA	macro	;x,y,col,An
+	move.w	\3,-(a7)
+	move.l	\4,-(a7)
+	move.w	\2,-(a7)
+	move.w	\1,-(a7)
+	jsr	doorsos::DrawStrXY
+	lea	10(a7),a7
+                endm
+
+GetKeyStat	MACRO
+		move.w		#$FFFE,d0
+		move.b		\1,d1
+		rol.w 		d1,d0
+		move.w		d0,($600018)
+		nop
+		nop
+		nop
+		nop
+		move.b		($60001B),d0
+		ENDM
+
+DEREF macro
+ doorsos::DEREF \1,\2
+ endm
+
+handle_ptr macro
+ DEREF \1,\2
+ endm
+
+doorsos::DEREF_SYM macro
+ move.l \1,-(sp)
+ jsr doorsos::DerefSym
+ add.l #4,sp
+ endm
+
+
+doorsos::ER_throw macro
+ dc.w $A000+\1
+ endm
+
+inc	MACRO
+	addq.\0	#1,\1
+	ENDM
+INC	MACRO
+	addq.\0	#1,\1
+	ENDM
+dec	MACRO
+	subq.\0	#1,\1
+	ENDM
+DEC	MACRO
+	subq.\0	#1,\1
+	ENDM
+
+
+push	MACRO
+	move.\0	\1,-(a7)
+	ENDM
+
+pop	MACRO
+	move.\0	(a7)+,\1
+	ENDM
+pushm	MACRO
+	movem.\0	\1,-(a7)
+	ENDM
+
+popm	MACRO
+	movem.\0	(a7)+,\1
+	ENDM
+
+PUSH	MACRO
+	move.\0	\1,-(a7)
+	ENDM
+
+POP	MACRO
+	move.\0	(a7)+,\1
+	ENDM
+PUSHM	MACRO
+	movem.\0	\1,-(a7)
+	ENDM
+
+POPM	MACRO
+	movem.\0	(a7)+,\1
+	ENDM
+
+
+_library
+_ti89
+_ti92plus

+ 43 - 0
tigcc/hsf2rc/hsf2RC.txt

@@ -0,0 +1,43 @@
+
+       hsf2RC ROM_CALL include builder for the TI-89 and TI-92 Plus 
+      ===============================================================
+
+Loïc YHUEL (hwti)	hwti@hotmail.com
+
+Copyright (C) 2002 Loïc YHUEL
+
+This archive contains :
+- the program ('hsf2RC.exe')
+- the source code ('hsf2RC.cpp')
+- configuration files : 'os.h.end', 'doorsos.h.end', 'NotDefinedRom_calls' and 'db92_alias'
+- license.txt : the GPL license
+- this document
+
+How to use it
+=============
+It must be launched in doc\System\Include subdirectory of TIGCC sources.
+If you run it without parameters it builds only 'doorsos.h' and 'os.h'.
+If you execute 'hsf2RC /db92' it will build DB92 ROM_CALLS include files ('Romcalls.bin' and 'romcalls.h') too.
+
+
+OPTIONS
+=======
+hsf2RC appends 'os.h.end' and 'doorsos.h.end' at the end of 'os.h' and 'doorsos.h'. They contains the macros and consts.
+You can modify them if you want.
+'NotDefinedRom_calls' contains ROM_CALLS which are not in TIGCC documentation because they are AMS1 specific or they are implemented as macros.
+
+
+DB92 SPECIFIC
+=============
+When you add the '/db92' switch, hsftoRC builds a list of the ROM_CALLS names for DB92.
+In this format, each ROM_CALL has an unique name, so :
+      -	if it sees a new name for an already named ROM_CALL, it asks you if you want to keep the first name or use the second
+   	In order to not ask the user each time, it saves the result in 'db92_alias' file wich has a simple format
+	"[ROM_CALL number in decimal] [y/n]" ('n' means that it keeps the first name, 'y' that it uses the second)
+      -	if a ROM_CALL is unnamed, it prints a warning and in DB92 it will show a blank name.
+
+
+Portability
+-----------
+This source code can be compiled without modifications under windows with MS VC++ 7.0 and MinGW32.
+I don't know if it can be compiled correctly under Linux. You should be able to use any C++ compiler.

+ 171 - 0
tigcc/hsf2rc/hsf2rc.cpp

@@ -0,0 +1,171 @@
+//hsf2RC.cpp copyright Loïc YHUEL (hwti) 2002
+
+//#define WIN32_LEAN_AND_MEAN		// Exclure les en-têtes Windows rarement utilisés
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+void WriteInfo(char *str1,char *str2);
+
+FILE *os,*doorsos,*alias;
+bool MakeDB92INFO;
+char *(*table)[2000];
+int Highest=-1;
+
+
+int main(int argc, char *argv[])
+{
+	_finddata_t data;
+	long file, folder;
+ 	FILE *f1,*db92;
+	char dummy[100],dummy2[100],path[50];
+	char * s,* c;
+	int b;
+
+	puts("Builds os.h, doorsos.h [and db92 rom_call info] from TIGCC sources\nhsf2RC [/db92]");
+	if ((argc > 1) && (!(stricmp("/db92",argv[1])))) {
+		MakeDB92INFO = true;
+		if (!(table = (char*(*)[2000])calloc(2000,sizeof(char *)))) {
+			puts("Out of memory");
+			return 1;
+		}
+		db92 = fopen("Romcalls.bin","wt");
+	}
+	else MakeDB92INFO = false;
+	
+	folder = _findfirst("*.h",&data);
+	if (folder == -1) {
+		puts("No directory found. Run hsf2rc in doc\\system\\include directory of TIGCC sources.");
+		return 1;
+	}
+	
+	os = fopen("os.h","wt");
+	doorsos = fopen("doorsos.h","wt");
+	alias = fopen("db92_alias","a+t");
+	
+	do {
+		if (!(data.attrib && _A_SUBDIR)) continue;
+		strcpy(path,data.name);
+		strcat(path,"\\");
+		c = strchr(path,0);
+		strcpy(c,"*.hsf");
+		file = _findfirst(path,&data);
+		if (file == -1) continue;
+		do {
+			strcpy(c,data.name);
+			f1 = fopen(path, "rt");
+			do {
+				if (!fgets(dummy,100,f1)) goto nextfile;
+			} while (strncmp("Name=",dummy,5));
+			do {
+				if (!fgets(dummy2,100,f1)) goto nextfile;
+			} while (strcmp("[ROM Call]\n",dummy2));
+			fgets(dummy2,100,f1);
+			*strchr(dummy+5,'\n') = 0;
+			WriteInfo(dummy+5,dummy2);
+	nextfile :
+			fclose(f1);
+		} while (!_findnext(file,&data));
+		_findclose(file);
+	} while (!_findnext(folder,&data));
+	_findclose(folder);
+	
+	if (f1 = fopen("notdefinedrom_calls","rt")) {
+		while (fgets(dummy,100,f1)) {
+			if (dummy[0] == ';') continue;
+			*(s = strchr(dummy,' ')) = 0;
+			WriteInfo(dummy,s+1);
+		}
+		fclose(f1);
+	}
+	
+	if (f1 = fopen("os.h.end","rt")) {
+		while (fgets(dummy,100,f1)) fputs(dummy,os);
+		fclose(f1);
+	}
+
+	if (f1 = fopen("doorsos.h.end","rt")) {
+		while (fgets(dummy,100,f1)) fputs(dummy,doorsos);
+		fclose(f1);
+	}
+
+	fclose(os);
+	fclose(doorsos);
+	
+	if (MakeDB92INFO) {
+		for (b = 0;b <= Highest;b++) {
+			if (!((*table)[b] == 0)) {
+				fputs((*table)[b],db92);
+				free((*table)[b]);
+			}
+			else printf("Warning : ROM_CALL %i not defined\n",b);
+			fputc(0,db92);
+		}
+		f1 = fopen("romcalls.h","w");
+		fprintf(f1,";Include file automatically generated by hsf2RC.\n"
+		";Copyright (C) 2002 Loïc YHUEL (hwti)\n"
+		"RCNum equ %i\n"
+		"ROM_CALLs_Names\n"
+		" incbin romcalls.bin",b-1);
+		fclose(f1);
+		free(table);
+		fclose(db92);
+	}
+	fclose(alias);
+	return 0;
+}
+
+void WriteInfo(char *str1,char *str2)
+{
+	int a,b;
+	char dummy[100];
+
+	str2 = strchr(str2,'$');
+	fprintf(os,"%s\t\tequ\t%s",str1,str2);
+	fprintf(doorsos,"doorsos::%s\tequ\t_ROM_CALL_%s",str1,str2 + 1);
+	if (MakeDB92INFO) {
+		str2 = strchr(str2,0) - 1;
+		if (*str2 == '\n') str2--;
+		a = 1;
+		b = 0;
+		while (1) {
+			if ((*str2 >= '0') && (*str2 <= '9')) b += a * (*str2 - '0');
+			else if ((*str2 >= 'A') && (*str2 <= 'F')) b += a * (*str2 - 'A' + 10);
+			else break;
+			a *= 16;
+			str2--;
+		}
+			
+		if (!((*table)[b] == NULL)) {
+			if (alias) {
+				rewind(alias);
+				while (fgets(dummy,100,alias)) {
+					if ((atoi(dummy) == b)) {
+						if (*(strchr(dummy,' ')+1) == 'n') return;
+						else goto overw;
+					}
+				}
+			}
+			printf("ROM_CALL %i is already named %s. Name it %s ?",b,(*table)[b],str1);
+			do {
+				a = getchar();
+				if (a == 'n') {
+					if (alias) fprintf(alias,"%i n\n",b);
+					return;
+				}
+			} while (!(a == 'y'));
+			if (alias) fprintf(alias,"%i y\n",b);
+			}
+			
+overw :
+		if (!((*table)[b] = (char *)realloc((*table)[b],strlen(str1)+1))) {
+			puts("Out of memory");
+			exit(1);
+		}
+
+		strcpy((*table)[b],str1);
+		if (b > Highest) Highest = b;
+	}
+}

+ 92 - 0
tigcc/hsf2rc/os.h.end

@@ -0,0 +1,92 @@
+
+ScreenClear equ $19e
+bcdadd equ $b6
+bcdcmp equ $bb
+bcddiv equ $b9
+bcdbcd equ $bd
+bcdmul equ $b8
+bcdneg equ $ba
+bcdsub equ $b7
+bcdlong equ $bc
+
+LCD_MEM equ $4c00
+doorsos::main_lcd equ LCD_MEM
+doorsos::globals equ $4c00
+
+ROM_CALL macro
+ move.l $C8,a4
+ move.l \1*4(a4),a4
+ jsr (a4)
+ endm
+
+ROM_CALL2 macro
+ move.l $C8,a4
+ move.l \1*4(a4),a4
+ endm
+
+inc	MACRO
+	addq.\0	#1,\1
+	ENDM
+INC	MACRO
+	addq.\0	#1,\1
+	ENDM
+dec	MACRO
+	subq.\0	#1,\1
+	ENDM
+DEC	MACRO
+	subq.\0	#1,\1
+	ENDM
+
+
+push	MACRO
+	move.\0	\1,-(a7)
+	ENDM
+
+pop	MACRO
+	move.\0	(a7)+,\1
+	ENDM
+pushm	MACRO
+	movem.\0	\1,-(a7)
+	ENDM
+
+popm	MACRO
+	movem.\0	(a7)+,\1
+	ENDM
+
+PUSH	MACRO
+	move.\0	\1,-(a7)
+	ENDM
+
+POP	MACRO
+	move.\0	(a7)+,\1
+	ENDM
+PUSHM	MACRO
+	movem.\0	\1,-(a7)
+	ENDM
+
+POPM	MACRO
+	movem.\0	(a7)+,\1
+	ENDM
+
+doorsos::SYM_ENTRY.name equ 0
+doorsos::SYM_ENTRY.flags equ 8
+doorsos::SYM_ENTRY.hVal equ $c
+doorsos::NULL equ 0
+doorsos::H_NULL equ 0
+doorsos::RAND_MAX equ $7fff
+ACTIVITY_IDLE equ 0
+ACTIVITY_BUSY equ 1
+ACTIVITY_PAUSED equ 2
+ER_STOP equ 2
+ER_DIMENSION equ 230
+ER_MEMORY equ 670
+ER_MEMORY_DML equ 810
+UNDEFINED_TAG equ $2a
+LIST_TAG equ $d9
+MATRIX_TAG equ $db
+END_TAG equ $e5
+CALC_TI89 equ 0
+CALC_TI92PLUS equ 1
+_nostub
+_ti89
+_ti92plus

BIN
tigcc/ide/AboutUnit.dfm


+ 55 - 0
tigcc/ide/AboutUnit.pas

@@ -0,0 +1,55 @@
+unit AboutUnit;
+
+interface
+
+uses
+	Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
+  Buttons, ExtCtrls, URLLabelUnit;
+
+type
+  TAboutForm = class(TForm)
+    FramePanel: TPanel;
+    ProgramIcon: TImage;
+    ProductNameLabel: TLabel;
+    VersionLabel: TLabel;
+    OKButton: TButton;
+    Label2: TLabel;
+    Label3: TLabel;
+    Label4: TLabel;
+    Label5: TLabel;
+    Label6: TLabel;
+    URLLabel1: TURLLabel;
+    URLLabel2: TURLLabel;
+    URLLabel3: TURLLabel;
+    URLLabel4: TURLLabel;
+    URLLabel5: TURLLabel;
+    Label1: TLabel;
+    URLLabel6: TURLLabel;
+    CopyrightLabel: TLabel;
+    Label8: TLabel;
+    Label9: TLabel;
+    URLLabel7: TURLLabel;
+    Label10: TLabel;
+    URLLabel8: TURLLabel;
+    Label7: TLabel;
+    URLLabel9: TURLLabel;
+    procedure FormCreate(Sender: TObject);
+  private
+	public
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	VersionUnit;
+
+procedure TAboutForm.FormCreate(Sender: TObject);
+begin
+	PixelsPerInch := 96;
+	VersionLabel.Caption := 'Version ' + TIGCCLongVersion;
+end;
+
+end.
+ 

+ 15 - 0
tigcc/ide/CalcUnit.pas

@@ -0,0 +1,15 @@
+unit CalcUnit;
+
+interface
+
+type
+	TCalcDest = (cdTI89, cdTI89Titanium, cdTI92Plus, cdV200, cdTI92);
+	TCalcDests = set of TCalcDest;
+
+const
+	FirstCalcDest = cdTI89;
+	LastCalcDest = cdTI92;
+
+implementation
+
+end.

+ 494 - 0
tigcc/ide/CodeCompletion/CodeCompletion.pas

@@ -0,0 +1,494 @@
+unit CodeCompletion;
+
+interface
+
+uses SysUtils, SourceFileUnit, Dialogs, Classes, MainUnit;
+
+const
+  DefautDesc = '';
+  CCFVersion: Byte = 2;
+  //  Zero: Cardinal = 0;
+
+type
+  TOnNeedFile = procedure(const FileName: string; out CCFData: string) of object;
+
+  TCompletionItem = class(TObject)
+  public
+    Left, Right: string;
+    Description: string;
+
+    Line: Cardinal;
+
+    // Not Saved
+    SourceFileName: string;
+
+    procedure ReadFromStream(F: TStream);
+    procedure WriteToStream(F: TStream);
+  end;
+
+  TCompletionList = class(TStringList)
+  protected
+    FIncluded: TStringList;
+    FOnNeed: TOnNeedFile;
+
+    function aGetObject(Index: Integer): TCompletionItem;
+    procedure aSetObject(Index: Integer; const Value: TCompletionItem);
+  public
+    constructor Create; reintroduce;
+    destructor Destroy; override;
+    function AddObject(const Symbol: string; Info: TCompletionItem): Integer; reintroduce;
+    procedure Clear; override;
+    property Completion[Index: Integer]: TCompletionItem read aGetObject write aSetObject;
+
+    procedure AddCompletion(CCFData: TStream); overload;
+    procedure AddCompletion(const CCFData: string); overload;
+
+    // Completion state
+    property IncludedFiles: TStringList read FIncluded;
+
+    // When a file is needed
+    property OnNeedFile: TOnNeedFile read FOnNeed write FOnNeed;
+  end;
+
+function ReadString(F: TStream; var S: string): Boolean;
+function WriteString(F: TStream; const S: string): Boolean;
+
+function FileToString(const FileName: string): string;
+
+// Remove comments from a C Source
+function GetIdent(const S: string; var aPos: Integer): string;
+procedure FilterComment(Src, Dst: TStrings);
+
+// Parse a C Source
+function MakeCCF_C(const UnitName: string; Src: TSourceTextSourceFile): string;
+
+// Parse an Header Source
+function MakeCCF_H(const UnitName: string; Lines: TStrings; FilterTo: TStrings = nil): string;
+
+implementation
+
+uses StrUtils, UtilsDos;
+
+// Routines
+
+function GetIdent(const S: string; var aPos: Integer): string;
+var
+  i, l: Integer;
+begin
+  i := aPos;
+  l := Length(S);
+  while (i <= l) and (S[i] = ' ') do
+    Inc(i);
+  while (i <= l) and (S[i] in ['a'..'z', 'A'..'Z', '0'..'9', '_', '#']) do
+    Inc(i);
+  Result := Copy(S, aPos, i - aPos);
+  aPos := i;
+end;
+
+function ReadString(F: TStream; var S: string): Boolean;
+var
+  B: Byte;
+begin
+  if F.Read(B, 1) = 1 then
+  begin
+    Setlength(S, B);
+    Result := F.Read(S[1], B) = B;
+  end
+  else
+  begin
+    Result := False;
+    S := '';
+  end;
+end;
+
+function WriteString(F: TStream; const S: string): Boolean;
+var
+  B: Byte;
+begin
+  B := Length(S);
+  Result := False;
+  if F.Write(B, 1) = 1 then
+    Result := F.Write(S[1], B) = B;
+end;
+
+function FileToString(const FileName: string): string;
+var
+  F: TFileStream;
+  c1, c2: Integer;
+begin
+  Result := '';
+  try
+    F := TFileStream.Create(FileName, fmOpenRead);
+    try
+      c1 := F.Size;
+      SetLength(Result, c1);
+      c2 := F.Read(Result[1], c1);
+      if c1 <> c2 then
+        SetLength(Result, c2);
+    finally
+      F.Free;
+    end;
+  except
+  end;
+end;
+
+procedure FilterComment(Src, Dst: TStrings);
+var
+  S, S2: string;
+  i, p: Integer;
+  InComment: Boolean;
+begin
+  InComment := False;
+  for i := 0 to Src.Count - 1 do
+  begin
+    S := Trim(Src[i]);
+
+    // Check end of comment
+    if InComment then
+    begin
+      p := Pos('*/', S);
+      if p = 0 then
+      begin
+        Dst.Add('');
+        Continue;
+      end
+      else
+      begin
+        InComment := False;
+        S := Copy(S, p + 2, MaxInt);
+      end;
+    end;
+
+    // Check line comment
+    p := Pos('//', S);
+    if p = 1 then
+    begin
+      Dst.Add('');
+      Continue;
+    end
+    else if p <> 0 then
+      S := Copy(S, 1, p - 1);
+
+    // Check start of comment
+    p := Pos('/*', S);
+    if p <> 0 then
+    begin
+      S2 := S;
+      S := Copy(S, 1, p - 1);
+      p := PosEx('*/', S2, p + 2);
+      InComment := p = 0;
+      if not InComment then
+      begin
+        InComment := False;
+        S := S + Copy(S2, p + 2, MaxInt);
+      end;
+    end;
+
+    // Add result
+    Dst.Add(S);
+  end;
+end;
+
+procedure ParseIncludes(Src, Dst: TStrings);
+var
+  i, p: Integer;
+  Line: string;
+begin
+  // find line which starts with '#include'
+  for i := 0 to Src.Count - 1 do
+  begin
+    Line := Trim(Src[i]);
+    if AnsiStartsText('#include', Line) then
+    begin
+      p := Pos('"', Line);
+      if P <> 0 then
+      begin
+        Line := Copy(Line, p + 1, MaxInt);
+        Line := Copy(Line, 1, Pos('"', Line) - 1);
+        Dst.Add(Trim(Line));
+      end
+      else
+      begin
+        p := Pos('<', Line);
+        if P <> 0 then
+        begin
+          Line := Copy(Line, p + 1, MaxInt);
+          Line := Copy(Line, 1, Pos('>', Line) - 1);
+          Dst.Add(Trim(Line));
+        end;
+      end;
+    end;
+  end;
+end;
+
+function MakeCCF_C(const UnitName: string; Src: TSourceTextSourceFile): string;
+var
+  Dst: TMemoryStream;
+
+  // Parse files included in the Source unit
+  procedure ParseInc;
+  var
+    Included: TStringList;
+    w: Word;
+    i: Integer;
+    Source: TStrings;
+  begin
+    Source := TStringList.Create;
+    FilterComment(Src.SourceEditor.Lines, Source);
+    Included := TStringList.Create;
+    Included.Sorted := True;
+    Included.Duplicates := dupIgnore;
+    ParseIncludes(Source, Included);
+    w := Included.Count;
+    // write result to stream
+    Dst.Write(w, 2);
+    for i := 0 to Included.Count - 1 do
+      WriteString(Dst, Included[i]);
+    Included.Free;
+    Source.Free;
+  end;
+  // Parse Functions
+  procedure ParseFuncs;
+  var
+    Funcs: TSourceFileFunctions;
+    Func: TSourceFileFunction;
+    i, p, c, l: Integer;
+    S: string;
+    Source: TStrings;
+  begin
+    Source := Src.SourceEditor.Lines;
+    Funcs := Src.GetFunctions;
+    c := Source.Count;
+    for i := 0 to Length(Funcs) - 1 do
+    begin
+      Func := Funcs[i];
+      if Func.Name <> '' then
+      begin
+        if (Func.ImplementationLine > 0) and (Func.ImplementationLine <= c) then
+          l := Func.ImplementationLine - 1
+        else if (Func.PrototypeLine > 0) and (Func.PrototypeLine <= c) then
+          l := Func.PrototypeLine - 1
+        else
+          l := -1;
+        if l > -1 then
+          S := Source[l];
+        if S <> '' then
+        begin
+          p := Pos(Func.Name, S);
+          WriteString(Dst, Func.Name);
+          Dst.Write(l, 4);
+          WriteString(Dst, '<c:Teal>func <c:Blue>' + Trim(Copy(S, 1, p - 1)));
+          WriteString(Dst, Trim(Copy(S, p + Length(Func.Name), MaxInt)));
+          WriteString(Dst, DefautDesc);
+        end;
+      end;
+    end;
+  end;
+begin
+  Dst := TMemoryStream.Create;
+  Dst.Write(CCFVersion, SizeOf(CCFVersion));
+  WriteString(Dst, UnitName);
+  ParseInc;
+  ParseFuncs;
+  SetString(Result, PChar(Dst.Memory), Dst.Size);
+  Dst.Free;
+end;
+
+function MakeCCF_H(const UnitName: string; Lines: TStrings; FilterTo: TStrings = nil): string;
+var
+  Dst: TMemoryStream;
+  Source: TStrings;
+
+  // Parse files included in the Source unit
+  procedure ParseInc;
+  var
+    Included: TStringList;
+    w: Word;
+    i: Integer;
+  begin
+    Included := TStringList.Create;
+    Included.Sorted := True;
+    Included.Duplicates := dupIgnore;
+    ParseIncludes(Source, Included);
+    w := Included.Count;
+    // write result to stream
+    Dst.Write(w, 2);
+    for i := 0 to Included.Count - 1 do
+      WriteString(Dst, Included[i]);
+    Included.Free;
+  end;
+
+  procedure ParseHeader;
+  var
+    i, p, c: Integer;
+    S, S2, Ident: string;
+  begin
+    c := Source.Count;
+    i := 0;
+    while i < c do
+    begin
+      S := Source[i];
+      if AnsiStartsText('#define', S) then
+      begin
+        p := 9;
+        Ident := GetIdent(S, p);
+        S2 := Trim(Copy(S, p, MaxInt));
+        if S2 <> '' then
+        begin
+          WriteString(Dst, Ident);
+          Dst.Write(i, 4);
+          WriteString(Dst, '<c:Green>macro');
+          WriteString(Dst, S2);
+          WriteString(Dst, '');
+        end
+      end
+      else
+      begin
+        // terminer cette partie du code :)
+      end;
+      Inc(i);
+    end;
+  end;
+
+begin
+  Dst := TMemoryStream.Create;
+  Dst.Write(CCFVersion, SizeOf(CCFVersion));
+
+  if Assigned(FilterTo) then
+    Source := FilterTo
+  else
+    Source := TStringList.Create;
+  Source.Clear;
+
+  FilterComment(Lines, Source);
+  WriteString(Dst, UnitName);
+  ParseInc;
+  ParseHeader;
+  SetString(Result, PChar(Dst.Memory), Dst.Size);
+
+  if FilterTo = nil then
+    Source.Free;
+  Dst.Free;
+end;
+
+{ TCompletionList }
+
+constructor TCompletionList.Create;
+begin
+	inherited;
+	CaseSensitive := True;
+	Sorted := True;
+  Duplicates := dupAccept;
+  FIncluded := TStringList.Create;
+  FIncluded.Sorted := True;
+  FIncluded.Duplicates := dupIgnore;
+end;
+
+destructor TCompletionList.Destroy;
+begin
+  Clear;
+  inherited;
+end;
+
+function TCompletionList.AddObject(const Symbol: string;
+  Info: TCompletionItem): Integer;
+begin
+  Result := inherited AddObject(Symbol, Info);
+end;
+
+procedure TCompletionList.Clear;
+var
+  i: Integer;
+begin
+  IncludedFiles.Clear;
+  for i := 0 to Count - 1 do
+    Objects[i].Free;
+  inherited;
+end;
+
+function TCompletionList.aGetObject(Index: Integer): TCompletionItem;
+begin
+  Result := TCompletionItem(Objects[Index]);
+end;
+
+procedure TCompletionList.aSetObject(Index: Integer;
+  const Value: TCompletionItem);
+begin
+  Objects[Index] := Value;
+end;
+
+procedure TCompletionList.AddCompletion(CCFData: TStream);
+var
+  aStream: TStream;
+  UnitName, S1, S2: string;
+  i, w: Word;
+  C: TCompletionItem;
+  B: Byte;
+begin
+  if (CCFData.Read(B, 1) <> 1) or (B <> CCFVersion) then
+    Exit; // Wrong Version
+  if ReadString(CCFData, UnitName) and (IncludedFiles.IndexOf(UnitName) = -1) and (CCFData.Read(w, 2) = 2) then
+  begin
+    IncludedFiles.Add(UnitName);
+    // Check for included files
+    for i := 1 to w do
+    begin
+      if ReadString(CCFData, S1) then
+      begin
+        if (IncludedFiles.IndexOf(S1) = -1) and Assigned(OnNeedFile) then
+        begin
+          OnNeedFile(S1, S2);
+          if S2 <> '' then
+          begin
+            aStream := TStringStream.Create(S2);
+            AddCompletion(aStream);
+            aStream.Free;
+          end;
+        end;
+      end
+      else
+        Exit;
+    end;
+    // Add completion info
+    while ReadString(CCFData, S1) do
+    begin
+      C := TCompletionItem.Create;
+      C.ReadFromStream(CCFData);
+      C.SourceFileName := UnitName;
+      if S1 <> '' then
+        AddObject(S1, C)
+      else
+        C.Free;
+    end;
+  end;
+end;
+
+procedure TCompletionList.AddCompletion(const CCFData: string);
+var
+  S: TStringStream;
+begin
+  S := TStringStream.Create(CCFData);
+  AddCompletion(S);
+  S.Free;
+end;
+
+{ TCompletionItem }
+
+procedure TCompletionItem.ReadFromStream(F: TStream);
+begin
+  F.Read(Line, SizeOf(Line));
+  ReadString(F, Left);
+  ReadString(F, Right);
+  ReadString(F, Description);
+end;
+
+procedure TCompletionItem.WriteToStream(F: TStream);
+begin
+  F.Write(Line, SizeOf(Line));
+  WriteString(F, Left);
+  WriteString(F, Right);
+  WriteString(F, Description);
+end;
+
+end.
+

BIN
tigcc/ide/CodeCompletion/CompletionForm.dfm


+ 776 - 0
tigcc/ide/CodeCompletion/CompletionForm.pas

@@ -0,0 +1,776 @@
+unit CompletionForm;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, MasterUnit,
+	Dialogs, StdCtrls, ComCtrls, CodeCompletion, SourceFileUnit, UtilsDos, MemoComponentUnit,
+	HtFormatting, Menus, ActnList;
+
+const
+	SymbolFileNotFound = 'Symbol %s is declared in %s, but file can''t be found!';
+	AddTemplatesMsg = 'To add templates, go to Preferences->Coding';
+
+type
+	TCompForm = class(TForm)
+		CompList: TListBox;
+		CompStatus: TStatusBar;
+		procedure FormCreate(Sender: TObject);
+		procedure FormDestroy(Sender: TObject);
+		procedure FormDeactivate(Sender: TObject);
+		procedure CompListDrawItem(Control: TWinControl; Index: Integer;
+			Rect: TRect; State: TOwnerDrawState);
+		procedure CompListDblClick(Sender: TObject);
+		procedure CompListKeyDown(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure CompListKeyUp(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure CompListKeyPress(Sender: TObject; var Key: Char);
+	private
+		procedure SetEditor(const Value: TMemoComponent);
+	protected
+		{ Déclarations protégées }
+		C: TCompletionList;
+		CompRow: Integer;
+		StopKey: Boolean;
+		HintWindow: THtHintWindow;
+
+		FSourceFile: TSourceFile;
+		FEditor: TMemoComponent;
+
+		procedure CreateParams(var Params: TCreateParams); override;
+		function GetFileData(const F: string): string;
+		procedure NeedFile(const FileName: string; out CCFData: string);
+
+	protected
+		// Be informed when active control change :)
+
+		OldActiveControlChange: TNotifyEvent;
+		procedure ActiveControlChange(Sender: TObject);
+	public
+		{ Déclarations publiques }
+
+		// Get & Replace word under caret
+		procedure DelimitateWord(const Line: string; var StartPos: Integer; out EndPos: Integer);
+		function GetWord(Full, RemoveSpace: Boolean): string;
+		procedure SetWord(const Value: string);
+
+		// Show Completion Windows
+		property List: TCompletionList read C;
+		procedure RebuildList;
+		procedure ShowCompletion;
+		procedure CloseCompletion;
+		procedure ApplyCompletion;
+
+		// Show an hint window about the symbol Symbol, or symbol under caret if ''
+		function ShowSymbolInfo(Symbol: string = ''): Boolean;
+		procedure CloseSymbolInfo;
+
+		// Find symbol declaration
+		procedure FindSymbolDecl;
+
+	protected
+		OldChange: TNotifyEvent;
+		OldKeyDown: TKeyEvent;
+		OldKeyPress: TKeyPressEvent;
+
+		// Redirect Event from Editor
+		procedure Editor_Enter(Sender: TMemoComponent);
+		procedure Editor_Exit(Sender: TObject);
+		procedure Editor_KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+		procedure Editor_KeyPress(Sender: TObject; var Key: Char);
+		procedure Editor_Change(Sender: TObject);
+
+	public
+		property Editor: TMemoComponent read FEditor write SetEditor;
+	end;
+
+var
+	CompForm: TCompForm;
+
+	// TIGCC integration
+function SourceFileFromEditor(M: TMemoComponent): TSourceFile;
+
+procedure InsertAction(Owner: TComponent; After: TMenuItem; Action: TBasicAction);
+procedure InsertsAction(Owner: TComponent; const Afters: array of TMenuItem; Action: TBasicAction);
+
+implementation
+
+uses Types, StrUtils, Math, TmpltForm, MainUnit;
+
+{$R *.dfm}
+
+function SourceFileFromEditor(M: TMemoComponent): TSourceFile;
+var
+	i: Integer;
+	Lst: TSourceFiles;
+	Src: TSourceFile;
+begin
+	Lst := MainForm.SourceFiles;
+	for i := 0 to Lst.Count - 1 do
+	begin
+		Src := TSourceFile(Lst.Items[i]);
+		if Src.Editor = M then
+		begin
+			Result := Src;
+			Exit;
+		end;
+	end;
+	Result := nil;
+end;
+
+procedure InsertAction(Owner: TComponent; After: TMenuItem; Action: TBasicAction);
+var
+	Item: TMenuItem;
+begin
+	Item := TMenuItem.Create(Owner);
+	Item.Action := Action;
+	with After.Parent do
+		Insert(IndexOf(After) + 1, Item);
+end;
+
+procedure InsertsAction(Owner: TComponent; const Afters: array of TMenuItem; Action: TBasicAction);
+var
+	i: Integer;
+begin
+	for i := Low(Afters) to High(Afters) do
+		InsertAction(Owner, Afters[i], Action);
+end;
+
+// GUI Methods
+
+procedure TCompForm.FormCreate(Sender: TObject);
+begin
+	C := TCompletionList.Create;
+	C.OnNeedFile := NeedFile;
+	HintWindow := THtHintWindow.Create(Self);
+	OldActiveControlChange := Screen.OnActiveControlChange;
+	Screen.OnActiveControlChange := ActiveControlChange;
+end;
+
+procedure TCompForm.FormDestroy(Sender: TObject);
+begin
+	if Assigned(Screen.OnActiveControlChange) then
+		Screen.OnActiveControlChange := OldActiveControlChange;
+	HintWindow.Free;
+	C.Free;
+end;
+
+procedure TCompForm.FormDeactivate(Sender: TObject);
+var
+	M: TMemoComponent;
+begin
+	M := Editor;
+	if (M = nil) or (not M.Focused) then
+		CloseCompletion;
+end;
+
+procedure TCompForm.CreateParams(var Params: TCreateParams);
+begin
+	inherited;
+	Params.Style := WS_POPUP or WS_SYSMENU or WS_THICKFRAME;
+end;
+
+procedure TCompForm.CompListDrawItem(Control: TWinControl; Index: Integer;
+	Rect: TRect; State: TOwnerDrawState);
+const
+	MinWidth = 62;
+var
+	C: TCompletionItem;
+	S: string;
+	Cnv: TCanvas;
+	Selected: Boolean;
+	W: Integer;
+begin
+	if (Index >= 0) and (Index < List.Count) then
+	begin
+		Cnv := CompList.Canvas;
+		Selected := odSelected in State;
+		C := List.Completion[Index];
+		S := List[Index];
+		if Assigned(C) then
+		begin
+			Cnv.Font.Style := [];
+			DrawHtText(C.Left, Rect, Cnv, W, Selected);
+			Inc(Rect.Left, W);
+		end;
+		if Rect.Left < MinWidth then
+			Rect.Left := MinWidth;
+		Inc(Rect.Left, 2);
+		Cnv.Font.Style := [fsBold];
+		DrawHtText(S, Rect, Cnv, W, Selected);
+		Inc(Rect.Left, W + 2);
+		if Assigned(C) then
+		begin
+			Cnv.Font.Style := [];
+			DrawHtText(C.Right, Rect, CompList.Canvas, Rect.Left, Selected);
+			if Selected then
+				CompStatus.SimpleText := C.Description;
+		end;
+	end;
+end;
+
+procedure TCompForm.CompListDblClick(Sender: TObject);
+begin
+	ApplyCompletion;
+end;
+
+// Completion Tools
+
+procedure TCompForm.RebuildList;
+var
+	S: TSourceFile;
+begin
+	List.Clear;
+	S := SourceFileFromEditor(Editor);
+	if Assigned(S) then
+	begin
+		if S is TCSourceFile then
+			List.AddCompletion(MakeCCF_C(ExtractFileName(S.FileName), TCSourceFile(S)))
+		else if S is THeaderSourceFile then
+			List.AddCompletion(MakeCCF_H(ExtractFileName(S.FileName), THeaderSourceFile(S).SourceEditor.Lines));
+	end;
+	CompList.Count := List.Count;
+end;
+
+procedure TCompForm.ShowCompletion;
+var
+	M: TMemoComponent;
+	P: TPoint;
+	i: Integer;
+begin
+	M := Editor;
+	CloseSymbolInfo;
+	if Assigned(M) then
+	begin
+		RebuildList;
+		CompRow := M.Selection.StartRowCol.Row;
+		P := M.Selection.StartPoint;
+		P := M.ClientToScreen(P);
+		Left := P.X + 4;
+		Top := P.Y + 20;
+		List.Find(GetWord(True, False), i);
+		CompList.ItemIndex := i;
+		LockWindowUpdate(M.ParentWindow);
+		Show;
+		M.SetFocus;
+		LockWindowUpdate(0);
+	end;
+end;
+
+procedure TCompForm.CloseCompletion;
+begin
+	Hide;
+end;
+
+function TCompForm.ShowSymbolInfo(Symbol: string = ''): Boolean;
+	function Similarity(const A, B: string): Integer;
+	var
+		i, l: Integer;
+	begin
+		l := Min(Length(A), Length(B));
+		i := 1;
+		while (i <= l) and (UpCase(A[i]) = UpCase(B[i])) do
+			Inc(i);
+		Result := Abs(i - l);
+	end;
+	function Similar(const A, B: string): Boolean;
+	var
+		l: Integer;
+	begin
+		l := Min(Length(A), Length(B));
+		Result := Similarity(A, B) < (l shr 1);
+	end;
+var
+	M: TMemoComponent;
+	P: TPoint;
+	R: TRect;
+	i: Integer;
+	C: TCompletionItem;
+	T: string;
+begin
+	CloseCompletion;
+	Result := False;
+	if Symbol = '' then
+		Symbol := GetWord(False, True);
+	if Symbol = '' then
+	begin
+		CloseSymbolInfo;
+		Exit;
+	end;
+
+	M := Editor;
+	if Assigned(M) then
+	begin
+		RebuildList;
+
+		// Find Symbol
+		if List.Find(Symbol, i) then
+			T := ''
+		else if (i >= 0) and (i < List.Count) then
+		begin
+			if i = 0 then
+			begin
+				if Similar(Symbol, List[i]) then
+					T := List[i] + ' ?'#13#10
+				else
+					Exit;
+			end
+			else
+			begin
+				if Similarity(Symbol, List[i - 1]) > Similarity(Symbol, List[i]) then
+					Dec(i);
+				if Similar(Symbol, List[i]) then
+					T := List[i] + ' ?'#13#10
+				else
+					Exit;
+			end;
+		end
+		else
+			Exit;
+
+		// Show Symbol info
+		C := List.Completion[i];
+		if Assigned(C) then
+		begin
+			T := T + C.Left + ' ' + C.Right + #13#10 + C.Description;
+			// Calc hint window position
+			CompRow := M.Selection.StartRowCol.Row;
+			P := M.ClientToScreen(M.Selection.StartPoint);
+			R := HintWindow.CalcHintRect(Screen.Width, T, nil);
+			Inc(R.Left, P.X + 4);
+			Inc(R.Right, P.X + 4);
+			Inc(R.Top, P.Y + 20);
+			Inc(R.Bottom, P.Y + 20);
+			LockWindowUpdate(M.ParentWindow);
+			HintWindow.ActivateHint(R, T);
+			Result := True;
+			M.SetFocus;
+
+			// Bug with TSourceFileForm ??!!
+			if Assigned(M.Parent) and (M.Parent is TForm) then
+				M.Parent.BringToFront;
+			LockWindowUpdate(0);
+		end;
+	end;
+end;
+
+procedure TCompForm.CloseSymbolInfo;
+begin
+	if IsWindowVisible(HintWindow.Handle) then
+		ShowWindow(HintWindow.Handle, SW_HIDE);
+end;
+
+procedure TCompForm.ApplyCompletion;
+var
+	i: Integer;
+begin
+	i := CompList.ItemIndex;
+	if (i >= 0) and (i < List.Count) then
+	begin
+		SetWord(List[i]);
+		CloseCompletion;
+	end;
+end;
+
+// Find Files
+
+function TCompForm.GetFileData(const F: string): string;
+var
+	S: TSourceFile;
+	Folder: string;
+begin
+	S := MainForm.SourceFiles.FindFileNameOnly(F);
+	Folder := WithBackslash(TIGCCFolder);
+	if Assigned(S) and (S is TSourceTextSourceFile) then
+		Result := TSourceTextSourceFile(S).Content
+	else if FileExists(ExpandFileName(F)) then
+		Result := FileToString(ExpandFileName(F))
+	else if FileExists(Folder + CIncludeLocation + F) then
+		Result := FileToString(Folder + CIncludeLocation + F)
+	else if FileExists(Folder + ASMIncludeLocation + F) then
+		Result := FileToString(Folder + ASMIncludeLocation + F)
+	else
+		Result := '';
+end;
+
+procedure TCompForm.NeedFile(const FileName: string; out CCFData: string);
+var
+	CCFName: string;
+	Lst: TStringList;
+begin
+	// Search CCF file
+	CCFName := WithBackslash(TIGCCFolder) + CompletionLocation + ChangeFileExt(FileName, '.ccf');
+	if FileExists(CCFName) then
+		CCFData := FileToString(CCFName)
+	else
+	begin
+		// No CCF ? Generate info from header...
+		if UpperCase(ExtractFileExt(FileName)) = '.H' then
+		begin
+			Lst := TStringList.Create;
+			Lst.Text := GetFileData(FileName);
+			if Lst.Count > 0 then
+				CCFData := MakeCCF_H(FileName, Lst);
+			Lst.Free;
+		end;
+	end;
+end;
+
+// Word manipulations
+
+procedure TCompForm.DelimitateWord(const Line: string; var StartPos: Integer; out EndPos: Integer);
+const
+	ValidChars = ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'];
+var
+	i, j, l: Integer;
+begin
+	i := StartPos - 1;
+	j := StartPos - 1;
+	l := Length(Line);
+	// Find start pos
+	while (i > 0) and (i <= l) and (Line[i] in ValidChars) do
+		Dec(i);
+	// Find end pos
+	while (j > 0) and (j <= l) and (Line[j] in ValidChars) do
+		Inc(j);
+	if j = StartPos - 1 then
+	begin
+		j := StartPos;
+		while (j > 0) and (j <= l) and (Line[j] in ValidChars) do
+			Inc(j);
+	end;
+	Dec(j);
+	Inc(i);
+	StartPos := i;
+	EndPos := j;
+end;
+
+function TCompForm.GetWord(Full, RemoveSpace: Boolean): string;
+var
+	M: TMemoComponent;
+	S: string;
+	T: TTextCell;
+	StPos, EndPos, l: Integer;
+begin
+	M := Editor;
+	Result := '';
+	if Assigned(M) then
+	begin
+		T := M.Selection.StartRowCol;
+		if (T.Row > 0) and (T.Row <= M.LineCount) then
+		begin
+			S := M.Lines[T.Row - 1];
+			StPos := T.Col;
+			l := Length(S);
+			if RemoveSpace and (StPos > 1) and (StPos <= l) then
+			begin
+				if S[StPos - 1] = ' ' then
+					Dec(StPos);
+				while (StPos > 1) and (S[StPos] in ['(', ' ']) do
+					Dec(StPos);
+			end;
+			DelimitateWord(S, StPos, EndPos);
+			if Full then
+				Result := Trim(Copy(S, StPos, EndPos - StPos + 1))
+			else
+				Result := Trim(Copy(S, StPos, T.Col - StPos));
+		end;
+	end;
+end;
+
+procedure TCompForm.SetWord(const Value: string);
+var
+	M: TMemoComponent;
+begin
+	M := Editor;
+	if Assigned(M) then
+	begin
+		with M.Selection do
+		begin
+			SelectWord;
+			Text := Value;
+		end;
+	end;
+end;
+
+// Editor Events
+
+procedure TCompForm.Editor_KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+	procedure Select(Direction, Page: Boolean);
+	var
+		HowMany, i, c: Integer;
+	begin
+		i := CompList.ItemIndex;
+		c := List.Count;
+		if Page then
+			HowMany := CompList.Height div CompList.ItemHeight
+		else
+			HowMany := 1;
+		if Direction then
+			Inc(i, HowMany)
+		else
+			Dec(i, HowMany);
+		if i <= 0 then
+			CompList.ItemIndex := 0
+		else if i >= c then
+			CompList.ItemIndex := c - 1
+		else
+			CompList.ItemIndex := i;
+	end;
+var
+	NewKey: Word;
+begin
+	if Assigned(OldKeyDown) then
+		OldKeyDown(Sender, Key, Shift);
+	if Visible then
+	begin
+		NewKey := 0;
+		case Key of
+			VK_ESCAPE: Close;
+			VK_RETURN:
+				begin
+					ApplyCompletion;
+					StopKey := True;
+				end;
+			VK_UP: Select(False, False);
+			VK_DOWN: Select(True, False);
+			VK_PRIOR: Select(False, True);
+			VK_NEXT: Select(True, True);
+			VK_HOME: CompList.ItemIndex := 0;
+			VK_END: CompList.ItemIndex := List.Count - 1;
+			VK_LEFT, VK_RIGHT:
+				begin
+					Editor_Change(Sender);
+					NewKey := Key;
+				end;
+		else
+			NewKey := Key;
+		end;
+		Key := NewKey;
+	end
+	else if (ssCtrl in Shift) and (Key = VK_SPACE) then
+	begin
+		Key := 0;
+		StopKey := True;
+		ShowCompletion;
+	end
+	else if (ssCtrl in Shift) and (Key = Ord('J')) then
+	begin
+		Key := 0;
+		StopKey := True;
+		if TemplateForm.Templates.Count > 0 then
+			TemplateForm.Show
+		else
+			ShowMessage(AddTemplatesMsg);
+	end
+	else if (Key in [VK_BACK, VK_ESCAPE]) then // or not (Key in [Ord('A')..Ord('Z'), Ord('0')..Ord('9')
+		CloseSymbolInfo;
+end;
+
+procedure TCompForm.Editor_KeyPress(Sender: TObject; var Key: Char);
+begin
+	if Assigned(OldKeyPress) then
+		OldKeyPress(Sender, Key);
+	if StopKey then
+	begin
+		Key := #0;
+		StopKey := False;
+	end
+	else
+	begin
+		case Key of
+			'(': if Visible or not IsWindowVisible(HintWindow.Handle) then ShowSymbolInfo;
+			')': CloseSymbolInfo;
+		end;
+	end;
+end;
+
+procedure TCompForm.Editor_Change(Sender: TObject);
+var
+	i: Integer;
+	M: TMemoComponent;
+begin
+	if Assigned(OldChange) then
+		OldChange(Sender);
+	M := Editor;
+	if Visible then
+	begin
+		if Assigned(M) then
+		begin
+			if CompRow <> M.Selection.StartRowCol.Row then
+				CloseCompletion
+			else
+			begin
+				List.Find(GetWord(False, False), i);
+				CompList.ItemIndex := i;
+			end;
+		end
+		else
+			CloseCompletion;
+	end
+	else if Assigned(M) and (CompRow <> M.Selection.StartRowCol.Row) then
+		CloseSymbolInfo;
+end;
+
+procedure TCompForm.Editor_Enter(Sender: TMemoComponent);
+begin
+	if Assigned(Sender) then
+	begin
+		FEditor := Sender;
+
+		CloseCompletion;
+		CloseSymbolInfo;
+
+		OldKeyDown := Editor.OnKeyDown;
+		OldKeyPress := Editor.OnKeyPress;
+		OldChange := Editor.OnChange;
+
+		Editor.OnKeyDown := Editor_KeyDown;
+		Editor.OnKeyPress := Editor_KeyPress;
+		Editor.OnChange := Editor_Change;
+		Editor.OnSelectionChange := Editor_Change;
+	end
+	else
+	begin
+		FEditor := nil;
+		OldKeyDown := nil;
+		OldKeyPress := nil;
+		OldChange := nil;
+	end;
+end;
+
+procedure TCompForm.Editor_Exit(Sender: TObject);
+begin
+	if Assigned(Editor) then
+	begin
+		Editor.OnKeyDown := OldKeyDown;
+		Editor.OnKeyPress := OldKeyPress;
+		Editor.OnChange := OldChange;
+		Editor.OnSelectionChange := OldChange;
+	end;
+	CloseSymbolInfo;
+	if not Focused then
+	begin
+		FEditor := nil;
+		CloseCompletion;
+	end;
+end;
+
+procedure TCompForm.CompListKeyDown(Sender: TObject; var Key: Word;
+	Shift: TShiftState);
+var
+	M: TMemoComponent;
+begin
+	M := Editor;
+	if Assigned(M) then
+	begin
+		M.HandleKeyDown(Key, Shift);
+		M.SetFocus;
+		Key := 0;
+	end
+	else
+		CloseCompletion;
+end;
+
+procedure TCompForm.CompListKeyUp(Sender: TObject; var Key: Word;
+	Shift: TShiftState);
+var
+	M: TMemoComponent;
+begin
+	M := Editor;
+	if Assigned(M) then
+	begin
+		M.HandleKeyUp(Key, Shift);
+		M.SetFocus;
+		Key := 0;
+	end
+	else
+		CloseCompletion;
+end;
+
+procedure TCompForm.CompListKeyPress(Sender: TObject; var Key: Char);
+var
+	M: TMemoComponent;
+begin
+	M := Editor;
+	if Assigned(M) then
+	begin
+		M.HandleKeyPress(Key);
+		M.SetFocus;
+	end;
+end;
+
+procedure TCompForm.FindSymbolDecl;
+var
+	i, p: Integer;
+	Symbol, S: string;
+	C: TCompletionItem;
+	SourceFile: TSourceFile;
+begin
+	RebuildList;
+	Symbol := GetWord(True, True);
+	if (Symbol <> '') and List.Find(Symbol, i) then
+	begin
+		C := List.Completion[i];
+		if Assigned(C) and (C.SourceFileName <> '') then
+		begin
+			SourceFile := MainForm.SourceFiles.FindFileNameOnly(C.SourceFileName);
+			if SourceFile = nil then
+			begin
+				if FileExists(ExpandFileName(C.SourceFileName)) then
+					SourceFile := MainForm.AddSourceFile(ExpandFileName(C.SourceFileName), True)
+				else if FileExists(WithBackslash(TIGCCFolder) + CIncludeLocation + C.SourceFileName) then
+					SourceFile := MainForm.AddSourceFile(WithBackslash(TIGCCFolder) + CIncludeLocation + C.SourceFileName, True)
+				else if FileExists(WithBackslash(TIGCCFolder) + ASMIncludeLocation + C.SourceFileName) then
+					SourceFile := MainForm.AddSourceFile(WithBackslash(TIGCCFolder) + ASMIncludeLocation + C.SourceFileName, True)
+			end;
+			if Assigned(SourceFile) and (SourceFile is TTextSourceFile) then
+				with TTextSourceFile(SourceFile).TextEditor do
+				begin
+					if (C.Line < Cardinal(Lines.Count)) then
+					begin
+						S := Lines[C.Line];
+						p := Pos(Symbol, S);
+						if p = 0 then
+							p := 1;
+					end
+					else
+						p := 1;
+					Selection.StartRowCol := TextCell(C.Line + 1, p);
+					Selection.RLength := 0;
+					Selection.ScrollInView(4);
+				end
+			else
+				ShowMessageFmt(SymbolFileNotFound, [Symbol, C.SourceFileName]);
+		end;
+	end;
+end;
+
+procedure TCompForm.ActiveControlChange(Sender: TObject);
+var
+	W: TWinControl;
+begin
+	W := Screen.ActiveControl;
+	if (W = Editor) or (W = Self) or (W = CompList) or (W = TemplateForm) or (W = TemplateForm.TmpltList) then
+		Exit;
+	if Assigned(W) and (W is TMemoComponent) then
+		Editor := TMemoComponent(W)
+	else
+		Editor := nil;
+	if Assigned(OldActiveControlChange) then
+		OldActiveControlChange(Sender);
+end;
+
+procedure TCompForm.SetEditor(const Value: TMemoComponent);
+begin
+	if Value <> FEditor then
+	begin
+		Editor_Exit(Self);
+		Editor_Enter(Value);
+		FEditor := Value;
+	end;
+end;
+
+end.
+

BIN
tigcc/ide/CodeCompletion/Editor/uBatch.dfm


+ 129 - 0
tigcc/ide/CodeCompletion/Editor/uBatch.pas

@@ -0,0 +1,129 @@
+unit uBatch;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, FileCtrl, uEditor, uHSFParser, MasterUnit;
+
+const
+  BrowseCaption = 'Select Directory';
+
+type
+  TBatchEdit = class(TForm)
+    WorkDirLbl: TLabel;
+    WorkDirEdit: TEdit;
+    WorkDirBtn: TButton;
+    HsfDirLbl: TLabel;
+    HsfDirEdit: TEdit;
+    HsfDirBtn: TButton;
+    GoBtn: TButton;
+    LogMemo: TMemo;
+    EnumCheck: TCheckBox;
+    procedure GoBtnClick(Sender: TObject);
+    procedure WorkDirBtnClick(Sender: TObject);
+    procedure HsfDirBtnClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+  private
+    { Déclarations privées }
+  public
+    { Déclarations publiques }
+    Editor: TCEditorForm;
+  end;
+
+var
+  BatchEdit: TBatchEdit;
+
+implementation
+
+{$R *.dfm}
+
+procedure TBatchEdit.GoBtnClick(Sender: TObject);
+
+  procedure Log(const S: string);
+  begin
+    LogMemo.Lines.Add(S);
+  end;
+
+const
+  Valids = faAnyFile and not (faDirectory or faSysFile or faHidden);
+var
+  Sr: TSearchRec;
+  Path, HSFs: string;
+  F: TFileStream;
+begin
+  DoEnum := EnumCheck.Checked;
+  LogMemo.Clear;
+  if Editor = nil then
+    Exit;
+
+  Path := IncludeTrailingPathDelimiter(WorkDirEdit.Text);
+  HSFs := IncludeTrailingPathDelimiter(HsfDirEdit.Text);
+  Log('Start processing...');
+  if FindFirst(Path + '*.h', Valids, Sr) = 0 then
+  begin
+    repeat
+      Log('Found: ' + Sr.Name);
+      Editor.Clear;
+      if Editor.ParseH(Path + Sr.Name) then
+      begin
+        Log('Processing ' + Sr.Name + ' ...');
+        if DirectoryExists(HSFs + Sr.Name) then
+        begin
+          ClearCompletion(Editor.Lst);
+          ImportDir(HSFs + Sr.Name, Editor, Editor.GetLine);
+          Log('Found HSF Files ...');
+        end;
+        try
+          F := TFileStream.Create(Path + ChangeFileExt(Sr.Name, '.ccf'), fmCreate);
+          try
+            Editor.SaveToStream(F);
+          finally
+            F.Free;
+          end;
+        except
+          Log('Error while saving ccf for ' + Sr.Name);
+        end;
+      end;
+      Editor.Modified := False;
+      Log('');
+    until FindNext(Sr) <> 0;
+    FindClose(Sr);
+  end;
+  Editor.Modified := False;
+  Log('Finished!');
+  DoEnum := True;
+end;
+
+procedure TBatchEdit.WorkDirBtnClick(Sender: TObject);
+var
+  Dir: string;
+begin
+  Dir := WorkDirEdit.Text;
+  if SelectDirectory(BrowseCaption, '', Dir) then
+    WorkDirEdit.Text := Dir;
+end;
+
+procedure TBatchEdit.HsfDirBtnClick(Sender: TObject);
+var
+  Dir: string;
+begin
+  Dir := HsfDirEdit.Text;
+  if SelectDirectory(BrowseCaption, '', Dir) then
+    HsfDirEdit.Text := Dir;
+end;
+
+procedure TBatchEdit.FormCreate(Sender: TObject);
+var
+  Folder: string;
+begin
+  Folder := IncludeTrailingPathDelimiter(TIGCCFolder);
+  WorkDirEdit.Text := Folder + CIncludeLocation;
+  Folder := Folder + 'Src\doc\System\Include';
+  if DirectoryExists(Folder) then
+    HsfDirEdit.Text := Folder
+  else
+    HsfDirEdit.Text := TIGCCFolder;
+end;
+
+end.

BIN
tigcc/ide/CodeCompletion/Editor/uEditor.dfm


+ 490 - 0
tigcc/ide/CodeCompletion/Editor/uEditor.pas

@@ -0,0 +1,490 @@
+unit uEditor;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ExtCtrls, StdCtrls, Buttons, Grids, ValEdit, Menus, FileCtrl,
+  ComCtrls, CodeCompletion, HtFormatting;
+
+const
+  DefautCaption = 'Completion Editor';
+  Cell_Left = ' Left';
+  Cell_Right = ' Right';
+  Cell_Name = ' Name';
+  Cell_Desc = ' Description';
+  Cell_Line = ' Line';
+  SaveModif = 'Save modifications ?';
+  SaveError = 'Error %s:'#13#10'%s';
+  PreviewLBl = 'Preview:';
+  BrowseHSF = 'Select Directory where HSF files are stored';
+  LoadingError = 'Error while loading! (%s error: %s)';
+
+type
+  TCEditorForm = class(TForm)
+    MenuPnl: TPanel;
+    NewBtn: TSpeedButton;
+    SaveBtn: TSpeedButton;
+    OpenBtn: TSpeedButton;
+    OpenDialog: TOpenDialog;
+    SaveDialog: TSaveDialog;
+    ToolsBtn: TSpeedButton;
+    ToolsMenu: TPopupMenu;
+    ParseHSF: TMenuItem;
+    MainPageControl: TPageControl;
+    InfoTab: TTabSheet;
+    ItemsTab: TTabSheet;
+    ItemsLbl: TLabel;
+    ItemsList: TListBox;
+    ItemBox: TGroupBox;
+    ItemEditor: TValueListEditor;
+    ApplyBtn: TButton;
+    UNameLbl: TLabel;
+    UNameEdit: TEdit;
+    IncludeLbl: TLabel;
+    IncludeMemo: TMemo;
+    DelBtn: TButton;
+    ParseHeader: TMenuItem;
+    OpenHeaderDialog: TOpenDialog;
+    N1: TMenuItem;
+    Batch1: TMenuItem;
+    PreviewBox: TPaintBox;
+    procedure NewBtnClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
+    procedure ApplyBtnClick(Sender: TObject);
+    procedure OpenBtnClick(Sender: TObject);
+    procedure SaveBtnClick(Sender: TObject);
+    procedure DelBtnClick(Sender: TObject);
+    procedure ItemsListClick(Sender: TObject);
+    procedure ItemEditorStringsChange(Sender: TObject);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    procedure ToolsBtnClick(Sender: TObject);
+    procedure ParseHSFClick(Sender: TObject);
+    procedure ParseHeaderClick(Sender: TObject);
+    procedure PreviewBoxPaint(Sender: TObject);
+    procedure ItemsListData(Control: TWinControl; Index: Integer;
+      var Data: string);
+    procedure Batch1Click(Sender: TObject);
+    procedure SetModified(Sender: TObject);
+  private
+    { Déclarations privées }
+  public
+    { Déclarations publiques }
+    Filename: string;
+    Locked, Modified: Boolean;
+    Lst, LastHeader: TStringList;
+    HSFDir: string;
+    procedure UpdatePreview;
+    procedure SetItem(const Name, Left, Right, Description: string; Line: Cardinal);
+
+    // Stream methods
+    procedure Clear;
+    procedure LoadFromStream(F: TStream);
+    procedure SaveToStream(F: TStream);
+
+    // Tools Method
+    function ParseH(const FileName: string): Boolean;
+
+    // Add Symbol Line
+    function GetLine(const Symbol: string): Integer;
+  end;
+
+var
+  CEditorForm: TCEditorForm;
+
+procedure ClearCompletion(Lst: TStrings);
+
+implementation
+
+{$R *.dfm}
+
+uses uHSFParser, Math, uBatch;
+
+procedure ClearCompletion(Lst: TStrings);
+var
+  i: Integer;
+begin
+  for i := 0 to Lst.Count - 1 do
+    Lst.Objects[i].Free;
+  Lst.Clear;
+end;
+
+procedure TCEditorForm.UpdatePreview;
+begin
+  PreviewBox.Repaint;
+end;
+
+procedure TCEditorForm.NewBtnClick(Sender: TObject);
+begin
+  Clear;
+end;
+
+procedure TCEditorForm.FormCreate(Sender: TObject);
+begin
+  LastHeader := TStringList.Create;
+  Lst := TStringList.Create;
+  Lst.Sorted := True;
+  ItemEditor.ColWidths[0] := 96;
+  ItemEditor.Strings.Clear;
+  ItemEditor.Strings.Add(Cell_Name + '=');
+  ItemEditor.Strings.Add(Cell_Left + '=');
+  ItemEditor.Strings.Add(Cell_Right + '=');
+  ItemEditor.Strings.Add(Cell_Desc + '=');
+  ItemEditor.Strings.Add(Cell_Line + '=');
+  Modified := False;
+  Clear;
+end;
+
+procedure TCEditorForm.FormDestroy(Sender: TObject);
+begin
+  ClearCompletion(Lst);
+  Lst.Free;
+  LastHeader.Free;
+end;
+
+procedure TCEditorForm.ApplyBtnClick(Sender: TObject);
+begin
+  SetItem(ItemEditor.Values[Cell_Name],
+    ItemEditor.Values[Cell_Left],
+    ItemEditor.Values[Cell_Right],
+    ItemEditor.Values[Cell_Desc],
+    StrToIntDef(ItemEditor.Values[Cell_Line], 0));
+end;
+
+procedure TCEditorForm.OpenBtnClick(Sender: TObject);
+var
+  F: TFileStream;
+begin
+  if CloseQuery and OpenDialog.Execute then
+  try
+    Lst.Clear;
+    IncludeMemo.Clear;
+    F := TFileStream.Create(OpenDialog.FileName, fmOpenRead);
+    try
+      LoadFromStream(F);
+      Filename := OpenDialog.FileName;
+      Caption := DefautCaption + ' - ' + ExtractFileName(Filename);
+    finally
+      F.Free;
+    end;
+  except
+    on E: Exception do
+      ShowMessageFmt(LoadingError, [E.ClassName, E.Message]);
+  end;
+  ItemsList.Count := Lst.Count;
+end;
+
+procedure TCEditorForm.SaveBtnClick(Sender: TObject);
+var
+  F: TFileStream;
+begin
+  if FileExists(Filename) or SaveDialog.Execute then
+  try
+    F := TFileStream.Create(SaveDialog.FileName, fmCreate);
+    SaveToStream(F);
+    F.Free;
+    Filename := SaveDialog.FileName;
+    Caption := DefautCaption + ' - ' + ExtractFileName(Filename);
+    Modified := False;
+  except
+    on E: Exception do
+      ShowMessageFmt(SaveError, [E.ClassName, E.Message]);
+  end;
+end;
+
+procedure TCEditorForm.DelBtnClick(Sender: TObject);
+var
+  i: Integer;
+begin
+  for i := Lst.Count - 1 downto 0 do
+    if ItemsList.Selected[i] then
+    begin
+      Lst.Objects[i].Free;
+      Lst.Delete(i);
+    end;
+  ItemsList.Count := Lst.Count;
+end;
+
+procedure TCEditorForm.ItemsListClick(Sender: TObject);
+var
+  i: Integer;
+  O: TCompletionItem;
+begin
+  if ItemsList.SelCount > 0 then
+  begin
+    i := ItemsList.ItemIndex;
+    ItemEditor.Strings.BeginUpdate;
+    ItemEditor.Values[Cell_Name] := Lst[i];
+    O := TCompletionItem(Lst.Objects[i]);
+    if Assigned(O) then
+    begin
+      ItemEditor.Values[Cell_Left] := O.Left;
+      ItemEditor.Values[Cell_Right] := O.Right;
+      ItemEditor.Values[Cell_Desc] := O.Description;
+      ItemEditor.Values[Cell_Line] := IntToStr(O.Line);
+    end;
+    ItemEditor.Strings.EndUpdate;
+    UpdatePreview;
+  end;
+end;
+
+procedure TCEditorForm.ItemEditorStringsChange(Sender: TObject);
+begin
+  UpdatePreview;
+  SetModified(Sender);
+end;
+
+procedure TCEditorForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+  CanClose := True;
+  if Modified then
+    case MessageDlg(SaveModif, mtConfirmation, mbYesNoCancel, 0) of
+      mrYes: SaveBtn.Click;
+      mrNo: ;
+    else
+      CanClose := False;
+    end;
+end;
+
+procedure TCEditorForm.ToolsBtnClick(Sender: TObject);
+var
+  P: TPoint;
+begin
+  P := Point(0, ToolsBtn.Height);
+  P := ToolsBtn.ClientToScreen(P);
+  ToolsMenu.Popup(P.X, P.Y);
+end;
+
+procedure TCEditorForm.ParseHeaderClick(Sender: TObject);
+begin
+  if OpenHeaderDialog.Execute then
+    ParseH(OpenHeaderDialog.FileName);
+end;
+
+procedure TCEditorForm.ParseHSFClick(Sender: TObject);
+begin
+  if SelectDirectory(BrowseHSF, '', HSFDir) then
+  begin
+    Locked := True;
+    Lst.BeginUpdate;
+    ImportDir(HSFDir, Self, GetLine);
+    Lst.EndUpdate;
+    Locked := False;
+    ItemsList.Count := Lst.Count;
+  end;
+end;
+
+procedure TCEditorForm.SetItem(const Name, Left, Right, Description: string; Line: Cardinal);
+var
+  i: Integer;
+  O: TCompletionItem;
+begin
+  if (Name <> '') then
+  begin
+    i := Lst.IndexOf(Name);
+    if i = -1 then
+    begin
+      O := TCompletionItem.Create;
+      i := Lst.AddObject(Name, O);
+    end
+    else
+      O := TCompletionItem(Lst.Objects[i]);
+    O.Left := Left;
+    O.Right := Right;
+    O.Description := Description;
+    O.Line := Line;
+    if not Locked then
+    begin
+      ItemsList.Count := Lst.Count;
+      ItemsList.ItemIndex := i;
+    end;
+    Modified := True;
+  end;
+end;
+
+procedure TCEditorForm.LoadFromStream(F: TStream);
+var
+  S: string;
+  i, W: Word;
+  C: TCompletionItem;
+  B: Byte;
+begin
+  if (F.Read(B, 1) = 1) and (B = CCFVersion) and ReadString(F, S) then
+  begin
+    // Set Unit Name
+    UNameEdit.Text := S;
+    if F.Read(W, 2) = 2 then
+    begin
+      // Load Includes List
+      IncludeMemo.Lines.Clear;
+      for i := 1 to W do
+      begin
+        if ReadString(F, S) then
+          IncludeMemo.Lines.Add(S)
+        else
+          Break;
+      end;
+      // Load Symbols List
+      while ReadString(F, S) do
+      begin
+        C := TCompletionItem.Create;
+        C.ReadFromStream(F);
+        Lst.AddObject(S, C);
+      end;
+    end;
+    ItemsList.Count := Lst.Count;
+  end;
+end;
+
+procedure TCEditorForm.PreviewBoxPaint(Sender: TObject);
+var
+  H, W: Integer;
+  C: TCanvas;
+  R: TRect;
+begin
+  C := PreviewBox.Canvas;
+  R := PreviewBox.ClientRect;
+  H := C.TextHeight(PreviewLbl) + 2;
+
+  try
+    C.FillRect(R);
+    // Draw Preview
+    C.TextRect(R, R.Left, R.Top, PreviewLbl);
+    Inc(R.Top, H);
+
+    // Draw Left
+    DrawHtText(ItemEditor.Values[Cell_Left], R, C, W, False);
+    Inc(R.Top, H);
+
+    // Draw Name
+    C.Font.Style := [fsBold];
+    C.TextRect(R, R.Left, R.Top, ItemEditor.Values[Cell_Name]);
+    C.Font.Style := [];
+    Inc(R.Top, H);
+
+    // Draw Right
+    DrawHtText(ItemEditor.Values[Cell_Right], R, C, W, False);
+    Inc(R.Top, H);
+
+    // Draw Description
+    C.TextRect(R, R.Left, R.Top, ItemEditor.Values[Cell_Desc]);
+    Inc(R.Top, H);
+
+  except
+    C.Font.Style := [];
+  end;
+end;
+
+procedure TCEditorForm.SaveToStream(F: TStream);
+var
+  i: Integer;
+  W: Word;
+begin
+  try
+    // Write CCF Version
+    F.Write(CCFVersion, SizeOf(CCFVersion));
+    // Write Unit Name
+    WriteString(F, UNameEdit.Text);
+    // Write Included Units
+    W := IncludeMemo.Lines.Count;
+    if F.Write(W, 2) = 2 then
+      for i := 0 to W - 1 do
+        if not WriteString(F, Trim(IncludeMemo.Lines[i])) then
+          Break;
+    // Write Symbols
+    for i := 0 to Lst.Count - 1 do
+    begin
+      if WriteString(F, Lst[i]) then
+        TCompletionItem(Lst.Objects[i]).WriteToStream(F)
+      else
+        Break;
+    end;
+  except
+  end;
+end;
+
+function TCEditorForm.ParseH(const FileName: string): Boolean;
+var
+  Src: TStringList;
+  S: TStream;
+begin
+  Src := TStringList.Create;
+  try
+    try
+      Src.LoadFromFile(FileName);
+      S := TStringStream.Create(MakeCCF_H(ExtractFileName(FileName), Src, LastHeader));
+      try
+        LoadFromStream(S);
+      finally
+        S.Free;
+      end;
+    finally
+      Src.Free;
+    end;
+    Result := True;
+  except
+    Result := False;
+  end;
+end;
+
+procedure TCEditorForm.Clear;
+begin
+  if CloseQuery then
+  begin
+    LastHeader.Clear;
+    Caption := DefautCaption;
+    Filename := '';
+    UNameEdit.Text := '';
+    IncludeMemo.Text := '';
+    ClearCompletion(Lst);
+    ItemsList.Count := 0;
+  end;
+end;
+
+procedure TCEditorForm.ItemsListData(Control: TWinControl; Index: Integer;
+  var Data: string);
+begin
+  if (Index >= 0) and (Index < Lst.Count) then
+    Data := Lst[Index]
+  else
+    ItemsList.Count := Lst.Count;
+end;
+
+procedure TCEditorForm.Batch1Click(Sender: TObject);
+var
+  B: TBatchEdit;
+begin
+  Locked := True;
+  B := TBatchEdit.Create(Self);
+  B.Editor := Self;
+  B.ShowModal;
+  B.Free;
+  Locked := False;
+end;
+
+procedure TCEditorForm.SetModified(Sender: TObject);
+begin
+  Modified := True;
+end;
+
+function TCEditorForm.GetLine(const Symbol: string): Integer;
+var
+  i, p: Integer;
+  S: string;
+begin
+  for i := 0 to LastHeader.Count - 1 do
+  begin
+    S := LastHeader[i];
+    p := Pos(Symbol, S);
+    if not ((p = 0) or ((p > 1) and (S[p - 1] in ['a'..'z', 'A'..'Z', '0'..'9', '$', '_']))) then
+      if GetIdent(S, p) = Symbol then
+      begin
+        Result := i;
+        Exit;
+      end;
+  end;
+  Result := 0;
+end;
+
+end.

+ 189 - 0
tigcc/ide/CodeCompletion/Editor/uHSFParser.pas

@@ -0,0 +1,189 @@
+unit uHSFParser;
+
+interface
+
+uses Classes, uEditor;
+
+type
+  TOnGetLine = function(const Symbol: string): Integer of object;
+
+procedure ImportFile(const FileName: string; F: TCEditorForm; GetLine: TOnGetLine);
+procedure ImportDir(Dir: string; F: TCEditorForm; GetLine: TOnGetLine);
+
+function SimplifyType(T: string): string;
+function SimplifyLeft(T: string; out Right: string): string;
+function FilterComment(const Comment: string): string;
+function FilterDesc(const Def: string): string;
+
+var
+  DoEnum: Boolean;
+
+implementation
+
+uses SysUtils, StrUtils, UtilsDos;
+
+function SimplifyType(T: string): string;
+begin
+  T := Trim(T);
+  if T = 'Type' then
+    Result := '<c:Olive>type'
+  else if T = 'Function' then
+    Result := '<c:Teal>func'
+  else if T = 'Constant' then
+    Result := '<c:Green>const'
+  else if T = 'Variable' then
+    Result := '<c:Maroon>var'
+  else if T = 'Enum' then
+    Result := '<c:Olive>enum'
+  else
+    Result := T;
+end;
+
+function SimplifyLeft(T: string; out Right: string): string;
+begin
+  T := Trim(T);
+  if AnsiStartsText('typedef', T) then
+  begin
+    Right := Copy(T, 9, MaxInt);
+    Result := '';
+  end
+  else if AnsiStartsText('CALLBACK', T) then
+  begin
+    Result := '<i>callback';
+    Right := Trim(Copy(T, 10, MaxInt)) + ' | ';
+  end
+  else if T = 'unknown_retval' then
+    Result := '?'
+  else if T = '#define' then
+    Result := ''
+  else
+    Result := T;
+end;
+
+function FilterComment(const Comment: string): string;
+var
+  i, j: Integer;
+begin
+  Result := '';
+  i := Pos('/*', Comment);
+  j := -1;
+  while i <> 0 do
+  begin
+    Result := Result + Copy(Comment, j + 2, i - j - 1);
+    j := PosEx('*/', Comment, i);
+    if j = 0 then
+    begin
+      j := MaxInt;
+      Break;
+    end;
+    i := PosEx('/*', Comment, j);
+  end;
+  Result := Result + Copy(Comment, j + 2, MaxInt);
+end;
+
+function FilterDesc(const Def: string): string;
+var
+  i, j: Integer;
+begin
+  Result := '';
+  i := Pos('<', Def);
+  j := 0;
+  while i <> 0 do
+  begin
+    Result := Result + Copy(Def, j + 1, i - j - 1);
+    j := PosEx('>', Def, i);
+    if j = 0 then
+    begin
+      j := MaxInt;
+      Break;
+    end;
+    i := PosEx('<', Def, j);
+  end;
+  Result := Result + Copy(Def, j + 1, MaxInt);
+end;
+
+procedure FilterEnum(const Definition, Description: string; F: TCEditorForm; Line: Integer);
+var
+  Items: TStringList;
+  i, p: Integer;
+  L, R, S: string;
+begin
+  Items := TStringList.Create;
+  p := Pos('{', Definition);
+  if p <> 0 then
+  begin
+    Inc(p);
+    Items.CommaText := Copy(Definition, p, PosEx('}', Definition, p) - p);
+    L := '<c:Olive>' + Trim(Copy(Definition, 1, p - 2));
+    for i := 0 to Items.Count - 1 do
+    begin
+      S := Trim(Items[i]);
+      p := Pos('=', S);
+      if P <> 0 then
+      begin
+        R := Trim(Copy(S, p + 1, MaxInt));
+        S := Trim(Copy(S, 1, p - 1));
+      end
+      else
+        R := '';
+      F.SetItem(S, L, R, Description, Line);
+    end;
+  end;
+  Items.Free;
+
+end;
+
+procedure ImportFile(const FileName: string; F: TCEditorForm; GetLine: TOnGetLine);
+var
+  Lst: TStringList;
+  Name, Left, Right, Description, Definition, Tmp: string;
+  i, Line: Integer;
+begin
+  Lst := TStringList.Create;
+  Lst.LoadFromFile(FileName);
+
+  Name := Lst.Values['Name'];
+  Definition := Lst.Values['Definition'];
+  Left := FilterComment(SimplifyType(Lst.Values['Type']) + ' <c:Blue>' + SimplifyLeft(Copy(Definition, 1, Pos(Name, Definition) - 1), Tmp));
+  Right := Tmp + Trim(Copy(Definition, Pos(Name, Definition) + Length(Name), MaxInt));
+
+  i := Lst.IndexOf('[Description]');
+  if i <> -1 then
+    Description := FilterDesc(Lst[i + 1])
+  else
+    Description := '';
+
+  if Assigned(GetLine) then
+    Line := GetLine(Name)
+  else
+    Line := 0;
+
+  F.SetItem(Name, Left, Right, Description, Line);
+
+  if DoEnum and (Lst.Values['SubType'] = 'Enumeration') then
+    FilterEnum(Definition, Description, F, Line);
+
+  Lst.Free;
+end;
+
+procedure ImportDir(Dir: string; F: TCEditorForm; GetLine: TOnGetLine);
+var
+  SR: TSearchRec;
+begin
+  Dir := IncludeTrailingPathDelimiter(Dir);
+  if FindFirst(Dir + '*.*', faAnyFile, SR) = 0 then
+  begin
+    repeat
+      if SR.Name[1] <> '.' then
+      begin
+        if SR.Attr and faDirectory = faDirectory then
+          ImportDir(Dir + SR.Name, F, GetLine)
+        else if UpperCase(ExtractFileExt(SR.Name)) = '.HSF' then
+          ImportFile(Dir + SR.Name, F, GetLine);
+      end;
+    until FindNext(SR) <> 0;
+    FindClose(SR);
+  end;
+end;
+
+end.

+ 196 - 0
tigcc/ide/CodeCompletion/HtFormatting.pas

@@ -0,0 +1,196 @@
+unit HtFormatting;
+
+interface
+
+uses Windows, Types, Classes, Graphics, Forms, Controls;
+
+// Show an hint window with formatted text
+
+type
+  THtHintWindow = class(THintWindow)
+  protected
+    procedure Paint; override;
+  public
+    function CalcHintRect(MaxWidth: Integer; const AHint: string;
+      AData: Pointer): TRect; override;
+  end;
+
+  // Draw text with a small HTML-like formatting
+  // Tags: B (bold), I (italic), U (underline) or S (strike-out)
+  //
+  // You can also use <C:Color> for changing text color
+
+procedure DrawHtTextEx(const Text: string; out PlainText: string; Rect: TRect; Cnv: TCanvas; var Width, Height: Integer; NoColor: Boolean);
+procedure DrawHtText(const Text: string; Rect: TRect; Cnv: TCanvas; var Width: Integer; NoColor: Boolean);
+
+procedure DrawMultiLineHtTextEx(const Text: string; out PlainText: string; Rect: TRect; Cnv: TCanvas; var Width, Height: Integer; NoColor: Boolean);
+procedure DrawMultiLineHtText(const Text: string; Rect: TRect; Cnv: TCanvas; var Width: Integer; NoColor: Boolean);
+
+implementation
+
+uses StrUtils, MaskUtils, UtilsDos;
+
+procedure DrawHtTextEx(const Text: string; out PlainText: string; Rect: TRect; Cnv: TCanvas; var Width, Height: Integer; NoColor: Boolean);
+var
+  i, l, p: Integer;
+  S: string;
+  X, BWidth: Integer;
+  C: Char;
+  OriginalColor: TColor;
+  OriginalStyle: TFontStyles;
+  Size: tagSIZE;
+begin
+  OriginalColor := Cnv.Font.Color;
+  OriginalStyle := Cnv.Font.Style;
+  l := Length(Text);
+  p := 0;
+  X := Rect.Left;
+  Height := 0;
+  PlainText := '';
+  BWidth := Cnv.TextWidth('<');
+  while p < l do
+  begin
+    i := p + 1;
+    p := PosEx('<', Text, i);
+    if p = 0 then
+      p := l + 1;
+
+    // Draw Text
+    S := Copy(Text, i, p - i);
+    Cnv.TextRect(Rect, Rect.Left, Rect.Top, S);
+    PlainText := PlainText + S;
+
+    // Update Size
+    Size := Cnv.TextExtent(S);
+    Inc(Rect.Left, Size.cx);
+    if Size.cy > Height then
+      Height := Size.cy;
+
+    if p <> l then
+    begin
+      C := UpCase(Text[p + 1]);
+      if C <> 'C' then
+      begin
+        case C of
+          'B': Cnv.Font.Style := Cnv.Font.Style + [fsBold];
+          'U': Cnv.Font.Style := Cnv.Font.Style + [fsItalic];
+          'I': Cnv.Font.Style := Cnv.Font.Style + [fsUnderline];
+          'S': Cnv.Font.Style := Cnv.Font.Style + [fsStrikeOut];
+          '/':
+            if p + 1 < l then
+            begin
+              case UpCase(Text[p + 2]) of
+                'B': Cnv.Font.Style := Cnv.Font.Style - [fsBold];
+                'U': Cnv.Font.Style := Cnv.Font.Style - [fsItalic];
+                'I': Cnv.Font.Style := Cnv.Font.Style - [fsUnderline];
+                'S': Cnv.Font.Style := Cnv.Font.Style - [fsStrikeOut];
+              end;
+            end;
+          '<':
+            begin
+              Cnv.TextRect(Rect, Rect.Left, Rect.Top, '<');
+              Inc(Rect.Left, BWidth);
+            end;
+        end;
+        p := PosEx('>', Text, p + 1);
+        if p = 0 then
+          p := l;
+      end
+      else
+      begin
+        Inc(P, 3);
+        i := PosEx('>', Text, p);
+        if i = 0 then
+          p := l
+        else
+        begin
+          S := Copy(Text, p, i - p);
+          if S <> '' then
+          begin
+            if not (S[1] in ['0'..'9', '$']) then
+              S := 'cl' + S;
+            try
+              if not NoColor then
+                Cnv.Font.Color := StringToColor(S);
+            except
+            end;
+          end;
+          p := i;
+        end;
+      end;
+    end
+    else
+      Break;
+  end;
+  Width := Rect.Left - X;
+  Cnv.Font.Color := OriginalColor;
+  Cnv.Font.Style := OriginalStyle;
+end;
+
+procedure DrawMultiLineHtTextEx(const Text: string; out PlainText: string; Rect: TRect; Cnv: TCanvas; var Width, Height: Integer; NoColor: Boolean);
+var
+  Lst: TStringList;
+  S: string;
+  i, W, H: Integer;
+begin
+  Lst := TStringList.Create;
+  Lst.Text := Text;
+  Height := 0;
+  Width := 0;
+  for i := 0 to Lst.Count - 1 do
+  begin
+    DrawHtTextEx(Lst[i], S, Rect, Cnv, W, H, NoColor);
+    if W > Width then
+      Width := W;
+    Inc(Height, H);
+    Inc(Rect.Top, H);
+    Lst[i] := S;
+  end;
+  PlainText := Lst.Text;
+  Lst.Free;
+end;
+
+procedure DrawHtText(const Text: string; Rect: TRect; Cnv: TCanvas; var Width: Integer; NoColor: Boolean);
+var
+  S: string;
+  H: Integer;
+begin
+  DrawHtTextEx(Text, S, Rect, Cnv, Width, H, NoColor);
+end;
+
+procedure DrawMultiLineHtText(const Text: string; Rect: TRect; Cnv: TCanvas; var Width: Integer; NoColor: Boolean);
+var
+  S: string;
+  H: Integer;
+begin
+  DrawMultiLineHtTextEx(Text, S, Rect, Cnv, Width, H, NoColor);
+end;
+
+{ THtHintWindow }
+
+function THtHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: string;
+  AData: Pointer): TRect;
+var
+  P: string;
+  R: TRect;
+  W, H: Integer;
+begin
+  R := Rect(2, 2, 2, 2);
+  Canvas.Font.Color := Screen.HintFont.Color;
+  DrawMultiLineHtTextEx(AHint, P, R, Self.Canvas, W, H, False);
+  Result := Rect(0, 0, W + 2, H + 2);
+end;
+
+procedure THtHintWindow.Paint;
+var
+  R: TRect;
+  W: Integer;
+begin
+  R := ClientRect;
+  Inc(R.Left, 2);
+  Inc(R.Top, 2);
+  Canvas.Font.Color := Screen.HintFont.Color;
+  DrawMultiLineHtText(Caption, R, Self.Canvas, W, False);
+end;
+
+end.

BIN
tigcc/ide/CodeCompletion/PrefFrame.dfm


+ 108 - 0
tigcc/ide/CodeCompletion/PrefFrame.pas

@@ -0,0 +1,108 @@
+unit PrefFrame;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, TmpltForm;
+
+type
+  TCodingExt = class(TFrame)
+    TemplateBox: TGroupBox;
+    CompBox: TGroupBox;
+    CompEditor: TButton;
+    TmpltList: TListBox;
+    IdLbl: TLabel;
+    CodeLbl: TLabel;
+    IdEdit: TEdit;
+    CodeMemo: TMemo;
+    ClearBtn: TButton;
+    ApplyBtn: TButton;
+    procedure CompEditorClick(Sender: TObject);
+    procedure TmpltListData(Control: TWinControl; Index: Integer;
+      var Data: string);
+    procedure ApplyBtnClick(Sender: TObject);
+    procedure ClearBtnClick(Sender: TObject);
+    procedure TmpltListClick(Sender: TObject);
+    procedure OnShow(Sender: TObject);
+  public
+    { Déclarations publiques }
+
+  end;
+
+implementation
+
+{$R *.dfm}
+
+uses uEditor;
+
+procedure TCodingExt.CompEditorClick(Sender: TObject);
+var
+  Form: TCEditorForm;
+begin
+  Form := TCEditorForm.Create(Self);
+  Form.ShowModal;
+  Form.Free;
+end;
+
+procedure TCodingExt.TmpltListData(Control: TWinControl; Index: Integer;
+  var Data: string);
+begin
+  if (Index >= 0) and (Index < TemplateForm.Templates.Count) then
+    Data := TemplateForm.Templates[Index];
+end;
+
+procedure TCodingExt.ApplyBtnClick(Sender: TObject);
+var
+  Id: string;
+  T: TTemplate;
+  i: Integer;
+begin
+  Id := Trim(IdEdit.Text);
+  if Id <> '' then
+  begin
+    if TemplateForm.Templates.Find(Id, i) then
+      TTemplate(TemplateForm.Templates.Objects[i]).Text := CodeMemo.Text
+    else
+    begin
+      T := TTemplate.Create;
+      T.Text := CodeMemo.Text;
+      TemplateForm.Templates.AddObject(Id, T);
+    end;
+  end;
+  TmpltList.Count := TemplateForm.Templates.Count;
+end;
+
+procedure TCodingExt.ClearBtnClick(Sender: TObject);
+var
+  i: Integer;
+begin
+  for i := TemplateForm.Templates.Count - 1 downto 0 do
+    if TmpltList.Selected[i] then
+    begin
+      TemplateForm.Templates.Objects[i].Free;
+      TemplateForm.Templates.Delete(i);
+    end;
+  TmpltList.Count := TemplateForm.Templates.Count;
+end;
+
+procedure TCodingExt.TmpltListClick(Sender: TObject);
+var
+  Index: Integer;
+begin
+  if TmpltList.SelCount > 0 then
+  begin
+    Index := TmpltList.ItemIndex;
+    IdEdit.Text := TemplateForm.Templates[Index];
+    CodeMemo.Text := TTemplate(TemplateForm.Templates.Objects[Index]).Text;
+  end;
+end;
+
+procedure TCodingExt.OnShow(Sender: TObject);
+begin
+  if TmpltList.Count <> TemplateForm.Templates.Count then
+    TmpltList.Count := TemplateForm.Templates.Count;
+end;
+
+end.
+

BIN
tigcc/ide/CodeCompletion/TmpltForm.dfm


+ 200 - 0
tigcc/ide/CodeCompletion/TmpltForm.pas

@@ -0,0 +1,200 @@
+unit TmpltForm;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, MemoComponentUnit;
+
+type
+	TTemplate = class(TObject)
+	public
+		Text: string;
+		procedure Apply(Dest: TMemoComponent);
+	end;
+
+	TTemplateForm = class(TForm)
+		TmpltList: TListBox;
+		procedure FormDeactivate(Sender: TObject);
+		procedure TmpltListData(Control: TWinControl; Index: Integer;
+			var Data: string);
+		procedure FormCreate(Sender: TObject);
+		procedure FormDestroy(Sender: TObject);
+		procedure TmpltListDblClick(Sender: TObject);
+		procedure TmpltListKeyDown(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure FormActivate(Sender: TObject);
+	public
+		{ Déclarations publiques }
+		Templates: TStringList;
+		procedure Select;
+	end;
+
+var
+	TemplateForm: TTemplateForm;
+
+implementation
+
+{$R *.dfm}
+
+uses MasterUnit, UtilsDos, CodeCompletion, CompletionForm;
+
+{ TTemplate }
+
+procedure TTemplate.Apply(Dest: TMemoComponent);
+var
+  St: Integer;
+  i, p: Integer;
+  S, Before: string;
+  Lst: TStringList;
+  T: TTextCell;
+begin
+  // Indent template
+  T := Dest.Selection.StartRowCol;
+  Before := Copy(Dest.Lines[T.Row - 1], 1, T.Col - 1);
+  Lst := TStringList.Create;
+  Lst.Text := Text;
+  for i := 1 to Lst.Count - 1 do
+    Lst[i] := Before + Lst[i];
+	S := Lst.Text;
+	if (Copy(S, Length(S) - 1, 2) = #13#10) and (Copy(Text, Length(Text) - 1, 2) <> #13#10) then
+		Delete(S, Length(S) - 1, 2);
+	Lst.Free;
+
+  p := Pos('|', S);
+
+  st := Dest.Selection.RStart;
+  if p = 0 then
+    Dest.Selection.Text := S
+  else
+  begin
+    Delete(S, p, 1);
+    Dest.Selection.Text := S;
+    Inc(St, p - 1);
+  end;
+  Dest.Selection.RStart := st;
+  Dest.Selection.RLength := 0;
+end;
+
+{ TTemplateForm }
+
+procedure TTemplateForm.FormDeactivate(Sender: TObject);
+begin
+  Hide;
+end;
+
+procedure TTemplateForm.TmpltListData(Control: TWinControl; Index: Integer;
+  var Data: string);
+begin
+  if (Index >= 0) and (Index < Templates.Count) then
+    Data := Templates[Index];
+end;
+
+procedure TTemplateForm.FormCreate(Sender: TObject);
+var
+  T: TTemplate;
+  F: TStream;
+  S: string;
+begin
+  Templates := TStringList.Create;
+  Templates.Sorted := True;
+	S := WithBackslash(TIGCCFolder) + TemplatesLocation + 'templates.dat';
+  if FileExists(S) then
+  try
+    F := TFileStream.Create(S, fmOpenRead);
+    try
+      while ReadString(F, S) do
+      begin
+        T := TTemplate.Create;
+        ReadString(F, T.Text);
+        Templates.AddObject(S, T);
+      end;
+    finally
+      F.Free;
+    end;
+  except
+  end;
+end;
+
+procedure TTemplateForm.FormDestroy(Sender: TObject);
+var
+  i: Integer;
+  F: TStream;
+  T: TTemplate;
+begin
+  try
+    F := TFileStream.Create(WithBackslash(TIGCCFolder) + TemplatesLocation + 'templates.dat', fmCreate);
+    try
+      for i := 0 to Templates.Count - 1 do
+      begin
+        T := TTemplate(Templates.Objects[i]);
+        if Assigned(T) then
+        begin
+          WriteString(F, Templates[i]);
+          WriteString(F, T.Text);
+        end;
+      end;
+    finally
+      F.Free;
+    end;
+  except
+  end;
+  for i := 0 to Templates.Count - 1 do
+    Templates.Objects[i].Free;
+  Templates.Free;
+end;
+
+procedure TTemplateForm.TmpltListDblClick(Sender: TObject);
+begin
+  Select;
+end;
+
+procedure TTemplateForm.TmpltListKeyDown(Sender: TObject; var Key: Word;
+  Shift: TShiftState);
+begin
+  case Key of
+    VK_RETURN:
+      Select;
+    VK_ESCAPE, VK_CLEAR, VK_BACK, VK_DELETE:
+      Hide;
+  end;
+
+end;
+
+procedure TTemplateForm.Select;
+var
+  Idx: Integer;
+  M: TMemoComponent;
+  T: TTemplate;
+begin
+  M := CompForm.Editor;
+  if Assigned(M) then
+  begin
+    Idx := TmpltList.ItemIndex;
+    if (Idx >= 0) and (Idx < Templates.Count) then
+    begin
+      T := TTemplate(Templates.Objects[Idx]);
+      if Assigned(T) then
+        T.Apply(M);
+    end;
+  end;
+  Hide;
+end;
+
+procedure TTemplateForm.FormActivate(Sender: TObject);
+var
+  M: TMemoComponent;
+  P: TPoint;
+begin
+	TmpltList.Count := Templates.Count;
+	M := CompForm.Editor;
+	if Assigned(M) then
+	begin
+		TmpltList.ItemIndex := 0;
+		P := M.ClientToScreen(M.Selection.StartPoint);
+		Left := P.X + 4;
+		Top := P.Y + 20;
+	end;
+end;
+
+end.

BIN
tigcc/ide/ColorsUnit.dfm


+ 120 - 0
tigcc/ide/ColorsUnit.pas

@@ -0,0 +1,120 @@
+unit ColorsUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  ExtCtrls, StdCtrls;
+
+type
+  TMultipleColorsForm = class(TForm)
+    ColorBox: TListBox;
+    Button1: TButton;
+    Button2: TButton;
+    Button3: TButton;
+    Bevel1: TBevel;
+    Button4: TButton;
+    Button5: TButton;
+    ColorDlg: TColorDialog;
+    procedure ColorBoxDrawItem(Control: TWinControl; Index: Integer;
+      Rect: TRect; State: TOwnerDrawState);
+    procedure EditColor(Sender: TObject);
+    procedure Button1Click(Sender: TObject);
+    procedure Button2Click(Sender: TObject);
+    procedure ColorBoxKeyDown(Sender: TObject; var Key: Word;
+      Shift: TShiftState);
+    procedure UpdateButtons(Sender: TObject);
+  private
+	public
+	end;
+
+implementation
+
+{$R *.DFM}
+
+procedure TMultipleColorsForm.ColorBoxDrawItem(Control: TWinControl; Index: Integer;
+	Rect: TRect; State: TOwnerDrawState);
+begin
+	with Control as TListBox do begin
+		if odSelected in State then
+			Canvas.Pen.Color := clHighlight
+		else
+			Canvas.Pen.Color := Color;
+		Canvas.MoveTo (Rect.Left, Rect.Top);
+		Canvas.LineTo (Rect.Right, Rect.Top);
+		Canvas.MoveTo (Rect.Left, Rect.Top + 1);
+		Canvas.LineTo (Rect.Right, Rect.Top + 1);
+		Canvas.MoveTo (Rect.Left, Rect.Bottom - 1);
+		Canvas.LineTo (Rect.Right, Rect.Bottom - 1);
+		Canvas.MoveTo (Rect.Left, Rect.Bottom - 2);
+		Canvas.LineTo (Rect.Right, Rect.Bottom - 2);
+		Canvas.MoveTo (Rect.Left, Rect.Top);
+		Canvas.LineTo (Rect.Left, Rect.Bottom);
+		Canvas.MoveTo (Rect.Left + 1, Rect.Top);
+		Canvas.LineTo (Rect.Left + 1, Rect.Bottom);
+		Canvas.MoveTo (Rect.Right - 1, Rect.Top);
+		Canvas.LineTo (Rect.Right - 1, Rect.Bottom);
+		Canvas.MoveTo (Rect.Right - 2, Rect.Top);
+		Canvas.LineTo (Rect.Right - 2, Rect.Bottom);
+		Inc (Rect.Left, 2);
+		Inc (Rect.Top, 2);
+		Dec (Rect.Right, 2);
+		Dec (Rect.Bottom, 2);
+		try
+			Canvas.Brush.Color := StrToInt (Items [Index]);
+		except
+			Canvas.Brush.Color := clBlack;
+		end;
+		Canvas.Brush.Style := bsSolid;
+		Canvas.FillRect (Rect);
+	end;
+end;
+
+procedure TMultipleColorsForm.EditColor(Sender: TObject);
+begin
+	if Button3.Enabled then begin
+		try
+			ColorDlg.Color := StrToInt (ColorBox.Items [ColorBox.ItemIndex]);
+		except
+			ColorDlg.Color := clBlack;
+		end;
+		if ColorDlg.Execute then
+			ColorBox.Items [ColorBox.ItemIndex] := '$' + UpperCase (IntToHex (ColorDlg.Color, 6));
+	end;
+end;
+
+procedure TMultipleColorsForm.Button1Click(Sender: TObject);
+var
+	I: Integer;
+begin
+	if ColorDlg.Execute then begin
+		I := ColorBox.Items.Add (UpperCase (IntToHex (ColorDlg.Color, 6)));
+		if ColorBox.Items [I] [1] <> '$' then
+			ColorBox.Items [I] := '$' + ColorBox.Items [I];
+	end;
+	UpdateButtons (Sender);
+end;
+
+procedure TMultipleColorsForm.Button2Click(Sender: TObject);
+begin
+	if Button2.Enabled then
+		ColorBox.Items.Delete (ColorBox.ItemIndex);
+	UpdateButtons (Sender);
+	if Button2.Enabled then
+		ColorBox.ItemIndex := ColorBox.Items.Count - 1;
+end;
+
+procedure TMultipleColorsForm.ColorBoxKeyDown(Sender: TObject;
+	var Key: Word; Shift: TShiftState);
+begin
+	if Key = vk_Delete then
+		Button2.Click;
+end;
+
+procedure TMultipleColorsForm.UpdateButtons(Sender: TObject);
+begin
+	Button2.Enabled := ColorBox.Items.Count > 0;
+	Button3.Enabled := Button2.Enabled;
+end;
+
+end.

BIN
tigcc/ide/CustomStyleUnit.dfm


+ 114 - 0
tigcc/ide/CustomStyleUnit.pas

@@ -0,0 +1,114 @@
+unit CustomStyleUnit;
+
+interface
+
+uses
+	SourceEditUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ExtCtrls;
+
+type
+	TCustomStyleForm = class(TForm)
+		Button1: TButton;
+		Button2: TButton;
+		Bevel1: TBevel;
+		Label1: TLabel;
+		Label2: TLabel;
+		Label3: TLabel;
+		BeginEdit: TEdit;
+		EndEdit: TEdit;
+		IgnoreEdit: TEdit;
+		Bevel2: TBevel;
+		Button3: TButton;
+		Button4: TButton;
+    ColorDlg: TColorDialog;
+    SwitchableCheckBox: TCheckBox;
+		procedure FormCreate(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
+    procedure BeginEditChange(Sender: TObject);
+    procedure EndEditChange(Sender: TObject);
+		procedure IgnoreEditChange(Sender: TObject);
+		procedure SwitchableCheckBoxClick(Sender: TObject);
+		procedure Button1Click(Sender: TObject);
+		procedure Button2Click(Sender: TObject);
+		procedure FormShow(Sender: TObject);
+	private
+	public
+		Style: TCustomStyle;
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	StyleSelectionUnit;
+
+procedure TCustomStyleForm.FormCreate(Sender: TObject);
+begin
+	Style := TCustomStyle.Create (nil);
+end;
+
+procedure TCustomStyleForm.FormDestroy(Sender: TObject);
+begin
+	Style.Free;
+end;
+
+procedure TCustomStyleForm.BeginEditChange(Sender: TObject);
+begin
+	Style.BeginText := BeginEdit.Text;
+end;
+
+procedure TCustomStyleForm.EndEditChange(Sender: TObject);
+begin
+	Style.EndText := EndEdit.Text;
+end;
+
+procedure TCustomStyleForm.IgnoreEditChange(Sender: TObject);
+begin
+	Style.IgnoreChar := IgnoreEdit.Text;
+end;
+
+procedure TCustomStyleForm.SwitchableCheckBoxClick(Sender: TObject);
+begin
+	Style.Switchable := SwitchableCheckBox.Checked;
+end;
+
+procedure TCustomStyleForm.Button1Click(Sender: TObject);
+begin
+	ColorDlg.Color := Style.Color;
+	if ColorDlg.Execute then begin
+		Style.Color := ColorDlg.Color;
+		Style.CustomColor := True;
+	end;
+end;
+
+procedure TCustomStyleForm.Button2Click(Sender: TObject);
+begin
+	with TStyleSelectionForm.Create (Self) do try
+		CustomStyle := Self.Style.CustomStyle;
+		Style := Self.Style.Style;
+		if ShowModal = mrOK then begin
+			Self.Style.CustomStyle := CustomStyle;
+			Self.Style.Style := Style;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TCustomStyleForm.FormShow(Sender: TObject);
+begin
+	if Style.BeginText = #13 then
+		BeginEdit.Text := '#13'
+	else
+		BeginEdit.Text := Style.BeginText;
+	if Style.EndText = #13 then
+		EndEdit.Text := '#13'
+	else
+		EndEdit.Text := Style.EndText;
+	IgnoreEdit.Text := Style.IgnoreChar;
+	SwitchableCheckBox.Checked := Style.Switchable;
+end;
+
+end.

+ 72 - 0
tigcc/ide/FolderUnit.pas

@@ -0,0 +1,72 @@
+unit FolderUnit;
+
+interface
+
+uses
+	Classes, ComCtrls;
+
+type
+	TFolder = class(TObject)
+	private
+		FTreeItem: TTreeNode;
+		function GetFolderName: string;
+		procedure SetFolderName(const Value: string);
+		function GetParent: TFolder;
+    function GetPath: string;
+	public
+		property Parent: TFolder read GetParent;
+	published
+		property FolderName: string read GetFolderName write SetFolderName;
+		property Path: string read GetPath;
+		property TreeItem: TTreeNode read FTreeItem write FTreeItem;
+	end;
+
+implementation
+
+uses
+	UtilsDos;
+
+{ TFolder }
+
+function TFolder.GetFolderName: string;
+begin
+	if Assigned (TreeItem) then
+		Result := TreeItem.Text
+	else
+		Result := '';
+end;
+
+function TFolder.GetParent: TFolder;
+var
+	ParentItem: TTreeNode;
+begin
+	Result := nil;
+	if Assigned (TreeItem) then begin
+		ParentItem := TreeItem.Parent;
+		if Assigned (ParentItem) and Assigned (ParentItem.Data) and (TObject (ParentItem.Data) is TFolder) then
+			Result := ParentItem.Data;
+	end;
+end;
+
+function TFolder.GetPath: string;
+var
+	P: TFolder;
+begin
+	P := Parent;
+	if Assigned (P) and (Length (P.FolderName) > 0) then begin
+		Result := P.Path;
+		if Length (Result) > 0 then
+			Result := WithBackslash (Result) + FolderName
+		else
+			Result := FolderName;
+	end else
+		Result := FolderName;
+end;
+
+procedure TFolder.SetFolderName(const Value: string);
+begin
+	if Assigned (TreeItem) then
+		TreeItem.Text := Value;
+end;
+
+end.

BIN
tigcc/ide/FunctionsWinUnit.dfm


+ 48 - 0
tigcc/ide/FunctionsWinUnit.pas

@@ -0,0 +1,48 @@
+unit FunctionsWinUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, SourceFileUnit;
+
+type
+  TFunctionsForm = class(TForm)
+    FuncList: TListBox;
+    PrototypeButton: TButton;
+    ImplementationButton: TButton;
+    CancelButton: TButton;
+    procedure FuncListDblClick(Sender: TObject);
+    procedure FuncListClick(Sender: TObject);
+		procedure FuncListMouseDown(Sender: TObject; Button: TMouseButton;
+			Shift: TShiftState; X, Y: Integer);
+	private
+	public
+		Funcs: PSourceFileFunctions;
+	end;
+
+implementation
+
+{$R *.DFM}
+
+procedure TFunctionsForm.FuncListDblClick(Sender: TObject);
+begin
+	if ImplementationButton.Enabled then
+		ModalResult := mrNo
+	else if PrototypeButton.Enabled then
+		ModalResult := mrYes;
+end;
+
+procedure TFunctionsForm.FuncListClick(Sender: TObject);
+begin
+	PrototypeButton.Enabled := (FuncList.ItemIndex >= 0) and (Funcs^[Integer(FuncList.Items.Objects[FuncList.ItemIndex])].PrototypeLine > 0);
+	ImplementationButton.Enabled := (FuncList.ItemIndex >= 0) and (Funcs^[Integer(FuncList.Items.Objects[FuncList.ItemIndex])].ImplementationLine > 0);
+end;
+
+procedure TFunctionsForm.FuncListMouseDown(Sender: TObject;
+	Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+begin
+	FuncListClick (Sender);
+end;
+
+end.

+ 36 - 0
tigcc/ide/IDE.cfg

@@ -0,0 +1,36 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J+
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-LE"c:\delphi\delphi6\Projects\Bpl"
+-LN"c:\delphi\delphi6\Projects\Bpl"
+-DCanSplit;CodingExt

+ 104 - 0
tigcc/ide/IDE.dof

@@ -0,0 +1,104 @@
+[FileVersion]
+Version=6.0
+
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=1
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+
+[Directories]
+OutputDir=
+UnitOutputDir=
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=
+Packages=VCL40;VCLX40
+Conditionals=CanSplit;CodingExt
+DebugSourceDirs=
+UsePackages=0
+
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=0
+MajorVer=2
+MinorVer=9
+Release=1
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1033
+CodePage=1252
+
+[Version Info Keys]
+CompanyName=TIGCC Team
+FileDescription=TIGCC IDE
+FileVersion=2.9.1.0
+InternalName=IDE
+LegalCopyright=Copyright (c) Sebastian Reichelt, 2000-2002
+LegalTrademarks=
+OriginalFilename=IDE.exe
+ProductName=TIGCC
+ProductVersion=0.95
+Comments=This program is freely distributable under the terms of the GNU General Public License.  It is kept open-source, but please email me at Sebastian@tigcc.ticalc.org if you found a bug or have a patch.
+
+[Excluded Packages]
+c:\delphi\delphi6\Bin\dcl31w60.bpl=Delphi 1.0 Compatibility Components
+c:\delphi\delphi6\Bin\dclsmp60.bpl=Borland Sample Components
+c:\delphi\delphi6\Bin\dclshlctrls60.bpl=Shell Control Property and Component Editors
+c:\delphi\delphi6\Bin\dclocx60.bpl=Borland Sample Imported ActiveX Controls
+
+[HistoryLists\hlConditionals]
+Count=2
+Item0=CanSplit;CodingExt
+Item1=CanSplit
+
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;

+ 65 - 0
tigcc/ide/IDE.dpr

@@ -0,0 +1,65 @@
+program IDE;
+
+uses
+  Forms,
+  Controls,
+  VersionUnit in 'VersionUnit.pas',
+	SourceFileUnit in 'SourceFileUnit.pas',
+  MasterUnit in 'MasterUnit.pas',
+	ParsingUnit in 'ParsingUnit.pas',
+  ProcessUnit in 'ProcessUnit.pas',
+  ToolsListUnit in 'ToolsListUnit.pas',
+  MainUnit in 'MainUnit.pas' {MainForm},
+  ProjectOptionsUnit in 'ProjectOptionsUnit.pas' {ProjectOptionsForm},
+  PreferencesUnit in 'PreferencesUnit.pas' {PreferencesForm},
+	AboutUnit in 'AboutUnit.pas' {AboutForm},
+  ProgramOptionsUnit in 'ProgramOptionsUnit.pas' {ProgramOptionsForm},
+	StyleSelectionUnit in 'StyleSelectionUnit.pas' {StyleSelectionForm},
+  ColorsUnit in 'ColorsUnit.pas' {MultipleColorsForm},
+  CustomStyleUnit in 'CustomStyleUnit.pas' {CustomStyleForm},
+  WordListUnit in 'WordListUnit.pas' {WordListForm},
+  StartupScreenUnit in 'StartupScreenUnit.pas' {StartupScreenForm},
+  SourceFileWinUnit in 'SourceFileWinUnit.pas' {SourceFileForm},
+	FunctionsWinUnit in 'FunctionsWinUnit.pas' {FunctionsForm},
+  OpenFileStatusUnit in 'OpenFileStatusUnit.pas' {OpenFileStatusForm},
+	NewsUnit in 'NewsUnit.pas' {NewsForm},
+  SendProgressUnit in 'SendProgressUnit.pas' {SendProgressForm},
+  ToolsUnit in 'ToolsUnit.pas' {ToolsForm},
+	ToolPropertiesUnit in 'ToolPropertiesUnit.pas' {ToolPropertiesForm},
+	ProgramOutputUnit in 'ProgramOutputUnit.pas' {ProgramOutputForm},
+	VTIStartUnit in 'VTIStartUnit.pas' {VTIStartForm},
+{$IFDEF CODINGEXT}
+	CodeCompletion in 'CodeCompletion\CodeCompletion.pas',
+	CompletionForm in 'CodeCompletion\CompletionForm.pas' {CompForm},
+	HtFormatting in 'CodeCompletion\HtFormatting.pas',
+	PrefFrame in 'CodeCompletion\PrefFrame.pas' {CodingExt: TFrame},
+	TmpltForm in 'CodeCompletion\TmpltForm.pas' {TemplateForm},
+	uBatch in 'CodeCompletion\Editor\uBatch.pas' {BatchEdit},
+	uEditor in 'CodeCompletion\Editor\uEditor.pas' {CEditorForm},
+	uHSFParser in 'CodeCompletion\Editor\uHSFParser.pas',
+{$ENDIF}
+	LinkDLLUnit in 'LinkDLLUnit.pas',
+	FolderUnit in 'FolderUnit.pas',
+	LinkUnit in 'LinkUnit.pas',
+	CalcUnit in 'CalcUnit.pas';
+
+{$R *.RES}
+
+begin
+	Application.Initialize;
+	Application.Title := 'TIGCC IDE';
+	Screen.Cursor := crAppStart;
+	StartupScreenForm := TStartupScreenForm.Create (Application);
+	StartupScreenForm.Show;
+	StartupScreenForm.Update;
+	StartupScreenForm.DisplayText := 'Creating Main Window...';
+	Application.CreateForm(TMainForm, MainForm);
+{$IFDEF CODINGEXT}
+	Application.CreateForm(TCompForm, CompForm);
+	Application.CreateForm(TTemplateForm, TemplateForm);
+{$ENDIF}
+	StartupScreenForm.Free;
+	StartupScreenForm := nil;
+	Screen.Cursor := crDefault;
+	Application.Run;
+end.

Різницю між файлами не показано, бо вона завелика
+ 127 - 0
tigcc/ide/IDE.dsk


BIN
tigcc/ide/IDE.res


+ 77 - 0
tigcc/ide/LinkDLLUnit.pas

@@ -0,0 +1,77 @@
+unit LinkDLLUnit;
+
+interface
+
+uses
+	Classes;
+
+const
+	LinkLibCurInterfaceVersion = 17;
+
+	llcdTI92         =  $01;
+	llcdTI89         =  $02;
+	llcdTI92Plus     =  $04;
+	llcdV200         =  $08;
+	llcdFlagTitanium = $100;
+
+	llffTIOS        = 0;
+	llffTIOSUpgrade = 1;
+
+	llfrMain = 0;
+	llfrData = 1;
+
+	llmtError   = 0;
+	llmtWarning = 1;
+
+type
+	TLinkLibDestFile = packed record
+		Data: Pointer;
+	end;
+
+	TLinkLibDataVarInfo = packed record
+		VarName: PChar;
+		CreateCopy,
+		CopyOnlyIfArchived: WordBool;
+	end;
+
+	TLinkLibOptimizeInfo = packed record
+		RemoveUnused,
+		OptimizeRelocs,
+		OptimizeNOPs,
+		OptimizeReturns,
+		OptimizeBranches,
+		OptimizeMoves,
+		OptimizeTests,
+		OptimizeCalcs,
+		UseFLineJumps,
+		Use4ByteFLineJumps,
+		CutRanges,
+		ReorderSections,
+		MergeConstants: WordBool;
+		ProgramSize,
+		DataSize,
+		BSSSize,
+		RelocCount,
+		NativeRelocCount,
+		OptimizeBranchesResult,
+		OptimizeMovesResult,
+		OptimizeTestsResult,
+		OptimizeCalcsResult,
+		UseFLineJumpsResult,
+		CutRangesResult,
+		NearAssemblyResult: LongInt;
+	end;
+
+	PCharArray = array [0..MaxListSize-1] of PChar;
+	PPChar = ^PCharArray;
+
+	TLinkLibGetInterfaceVersion = function: LongInt; cdecl;
+	TLinkLibGetOutputFile = function (var DestFile: TLinkLibDestFile; FileSize, DestCalc, FileRole, FileFormat, FileType: LongInt; Extension: PChar; Executable: WordBool; var EffectiveSize: LongInt): WordBool; cdecl;
+	TLinkLibFinalizeOutputFile = procedure (var DestFile: TLinkLibDestFile); cdecl;
+	TLinkLibError = procedure (FileName, Text: PChar; MessageType: LongInt); cdecl;
+	TLinkLibLinkFiles = function (ObjectFiles, ArchiveFiles: PPChar; ErrorMessage: TLinkLibError; GetOutputFile: TLinkLibGetOutputFile; FinalizeOutputFile: TLinkLibFinalizeOutputFile; NativeMode, FlashOS, Fargo: WordBool; var DataVarInfo: TLinkLibDataVarInfo; var OptimizeInfo: TLinkLibOptimizeInfo; OmitBSSInitialization: WordBool): ShortInt; cdecl;
+	TLinkLibCreateArchive = function (DestFile: PChar; ObjectFiles: PPChar; ErrorMessage: TLinkLibError; NoNames: WordBool): ShortInt; cdecl;
+
+implementation
+
+end.

+ 682 - 0
tigcc/ide/LinkUnit.pas

@@ -0,0 +1,682 @@
+unit LinkUnit;
+
+{	Uncomment to enable logging of all bytes sent and received to
+	C:\Linklog.txt. }
+(* {$DEFINE LOGLINK} *)
+
+interface
+
+uses
+	CalcUnit,
+	Windows, Classes;
+
+{ Calculator-specific Types }
+type
+	{ Enumeration Types }
+	TLinkPortType = (lpCOM);
+	TLinkCableType = (lcBlack, lcGray);
+	TCalcVarTypeID = Byte;
+
+	TLinkPort = record
+		PortType: TLinkPortType;
+		PortNumber: Cardinal;
+	end;
+
+	TLinkConnection = record
+		Port: TLinkPort;
+		CableType: TLinkCableType;
+		CalcType: TCalcDest;
+		Open: Boolean;
+		PortHandle: THandle;
+	end;
+
+	{	Variable or Folder Name }
+	TCalcVarName = array [0..9] of Char;
+
+	{	Variable Structure }
+	TCalcVar = record
+		CalcType: TCalcDest;
+		Folder,
+		Name: TCalcVarName;
+		TypeID: TCalcVarTypeID;
+		Size: LongWord;
+	end;
+
+	{	Progress callback function
+		Should return False if cancelled, True otherwise }
+	TProgressCallBack = function(ID: Pointer; Progress: PDWord): Boolean; 
+
+	{	Variable list callback function
+		This type is called by GetVarList on every item found }
+	TVarListCallBack = function(ID: Pointer; const NewVar: TCalcVar): Boolean; 
+
+{ Exported Functions }
+function CreateConnection(var Connection: TLinkConnection): Boolean;
+function OpenConnection(var Connection: TLinkConnection): Boolean;
+procedure CloseConnection(var Connection: TLinkConnection);
+
+function CalcReady(var Connection: TLinkConnection): Boolean; 
+
+function SendAck(var Connection: TLinkConnection): Boolean; 
+function SendWait(var Connection: TLinkConnection): Boolean; 
+function SendByte(var Connection: TLinkConnection; Value: Byte; CheckSum: PWord = nil): Boolean; 
+function SendWord(var Connection: TLinkConnection; Value: Word; CheckSum: PWord = nil): Boolean; 
+function SendLongWord(var Connection: TLinkConnection; Value: LongWord; CheckSum: PWord = nil): Boolean;
+function SendString(var Connection: TLinkConnection; Value: PChar; CheckSum: PWord = nil): Boolean;
+function SendKey(var Connection: TLinkConnection; Key: Char): Boolean;  overload;
+function SendKey(var Connection: TLinkConnection; Key: Word): Boolean;  overload;
+function SendKeys(var Connection: TLinkConnection; const Keys: string): Boolean;
+function SendVar(var Connection: TLinkConnection; Folder, Name: PChar; Buffer: Pointer; BufSize: Cardinal; Progress: PDWord = nil; ProgressCallBack: TProgressCallBack = nil; ID: Pointer = nil): Boolean;
+function SendFile(var Connection: TLinkConnection; Folder, Name: PChar; const FileName: string; Progress: PDWord = nil; ProgressCallBack: TProgressCallBack = nil; ID: Pointer = nil): Boolean;
+function ExecuteHomeLine(var Connection: TLinkConnection; const Line: string): Boolean;
+
+function CheckFileFormat(var Connection: TLinkConnection; const FileName: string; Folder: PChar = nil; Name: PChar = nil; Size: PWord = nil): Boolean;
+
+function WaitForAck(var Connection: TLinkConnection; LastResult: PByte = nil): Boolean;
+function CalcWaiting(var Connection: TLinkConnection; LastResult: PByte = nil): Boolean;
+function ReceiveByte(var Connection: TLinkConnection; out Value: Byte; CheckSum: PWord = nil): Boolean;
+function ReceiveWord(var Connection: TLinkConnection; out Value: Word; CheckSum: PWord = nil): Boolean;
+function ReceiveLongWord(var Connection: TLinkConnection; out Value: LongWord; CheckSum: PWord = nil): Boolean;
+
+function GetCalcType(var Connection: TLinkConnection): Boolean;
+
+implementation
+
+uses
+	SysUtils, Registry, ComServ;
+
+const
+	SendRetry = 1;
+	SendTimeout = 500;
+	ReceiveTimeout = 2000;
+	SleepBetweenReady = 500;
+	FirstReadyTimeout = 5000;
+	NormalReadyTimeout = 5000;
+	SendVarTimeout = 2000;
+	ProgressInterval = 100;
+	NonBlockingRead = False;
+	NonBlockingWrite = True;
+
+{$IFDEF LOGLINK}
+var
+	LogFile: Text;
+	LogSend: Boolean;
+{$ENDIF}
+
+var
+	OpenedOnce: Boolean = False;
+
+function GetPortState(Handle: THandle): Cardinal; forward;
+procedure SetPortState(Handle: THandle; State: Cardinal); forward;
+function GetPortName(const Port: TLinkPort): string; forward;
+function IsValidAck(Value: Byte): Boolean; forward;
+
+{	Creates a connection, opening the link port, but does not transfer any
+	data. }
+function CreateConnection(var Connection: TLinkConnection): Boolean; 
+var
+	NewHandle: THandle;
+	Settings: TDCB;
+	Timeouts: TCommTimeouts;
+begin
+	Result := False;
+	NewHandle := CreateFile (PChar (GetPortName (Connection.Port) + ':'), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+	if NewHandle = INVALID_HANDLE_VALUE then
+		Exit;
+	if Connection.CableType = lcBlack then begin
+		if not SetCommBreak (NewHandle) then begin
+			CloseHandle (NewHandle);
+			Exit;
+		end;
+	end else begin
+		if not SetupComm (NewHandle, 1024, 1024) then begin
+			CloseHandle (NewHandle);
+			Exit;
+		end;
+		FillChar (Settings, SizeOf (Settings), 0);
+		with Settings do begin
+			DCBLength := SizeOf (Settings);
+			BaudRate := CBR_9600;
+			ByteSize := 8;
+			StopBits := ONESTOPBIT;
+			Flags := $00001001;
+		end;
+		if not SetCommState (NewHandle, Settings) then begin
+			CloseHandle (NewHandle);
+			Exit;
+		end;
+		FillChar (Timeouts, SizeOf (Timeouts), 0);
+		with Timeouts do begin
+			ReadIntervalTimeout := MaxDWord;
+			if not NonBlockingRead then
+				ReadTotalTimeoutConstant := ReceiveTimeout;
+			if not NonBlockingWrite then
+				WriteTotalTimeoutConstant := SendTimeOut;
+		end;
+		if not SetCommTimeouts (NewHandle, Timeouts) then begin
+			CloseHandle (NewHandle);
+			Exit;
+		end;
+	end;
+	Connection.PortHandle := NewHandle;
+	Result := True;
+end;
+
+{	Opens a connection if it is not already open. }
+function OpenConnection(var Connection: TLinkConnection): Boolean; 
+var
+	Timeout,
+	StartTime: Cardinal;
+begin
+	if Connection.Open then
+		Result := True
+	else begin
+		{$IFDEF LOGLINK}
+			AssignFile (LogFile, 'C:\Linklog.txt');
+			ReWrite (LogFile);
+			Write (LogFile, ' - Calculator Link Log - ');
+			LogSend := False;
+		{$ENDIF}
+		Connection.Open := True;
+		if OpenedOnce then
+			Timeout := NormalReadyTimeout
+		else
+			Timeout := FirstReadyTimeout;
+		StartTime := GetTickCount;
+		repeat
+			Result := CalcReady (Connection);
+			if not Result then
+				Sleep (SleepBetweenReady);
+		until Result or (GetTickCount - StartTime > Timeout);
+		OpenedOnce := True;
+		if not Result then
+			Connection.Open := False;
+	end;
+end;
+
+{	Closes a connection if it is open, and frees the handle. }
+procedure CloseConnection(var Connection: TLinkConnection);
+begin
+	if Connection.CableType = lcBlack then
+		SetPortState (Connection.PortHandle, 0);
+	CloseHandle (Connection.PortHandle);
+	{$IFDEF LOGLINK}
+		CloseFile (LogFile);
+	{$ENDIF}
+end;
+
+procedure ResetConnection(var Connection: TLinkConnection);
+begin
+	if Connection.CableType = lcBlack then
+		SetPortState (Connection.PortHandle, 0);
+end;
+
+function WaitForAck(var Connection: TLinkConnection; LastResult: PByte = nil): Boolean;
+var
+	TempResult: Byte;
+begin
+	Result :=
+		ReceiveByte (Connection, TempResult) and IsValidAck (TempResult) and
+		ReceiveByte (Connection, TempResult) and (TempResult = $56) and
+		ReceiveByte (Connection, TempResult) and
+		ReceiveByte (Connection, TempResult);
+	if Assigned (LastResult) then
+		LastResult^ := TempResult;
+end;
+
+function CalcReady(var Connection: TLinkConnection): Boolean;
+var
+	TempResult: Byte;
+begin
+	Result := False;
+	if not
+		(SendByte (Connection, $09) and
+		SendByte (Connection, $68) and
+		SendByte (Connection, $00) and
+		SendByte (Connection, $00) and
+		WaitForAck (Connection) and
+		SendByte (Connection, $08) and
+		SendByte (Connection, $68) and
+		SendByte (Connection, $00) and
+		SendByte (Connection, $00) and
+		ReceiveByte (Connection, TempResult) and IsValidAck (TempResult)) then
+		Exit;
+	case TempResult of
+		$98, $89: Connection.CalcType := cdTI89;
+		$88:      Connection.CalcType := cdTI92Plus;
+		else Exit;
+	end;
+	Result :=
+		ReceiveByte (Connection, TempResult) and (TempResult = $56) and
+		ReceiveByte (Connection, TempResult) and
+		ReceiveByte (Connection, TempResult);
+end;
+
+function CalcWaiting(var Connection: TLinkConnection; LastResult: PByte = nil): Boolean;
+var
+	TempResult: Byte;
+begin
+	Result :=
+		ReceiveByte (Connection, TempResult) and IsValidAck (TempResult) and
+		ReceiveByte (Connection, TempResult) and (TempResult = $09) and
+		ReceiveByte (Connection, TempResult) and
+		ReceiveByte (Connection, TempResult);
+	if Assigned (LastResult) then
+		LastResult^ := TempResult;
+end;
+
+function SendAck(var Connection: TLinkConnection): Boolean;
+begin
+	Result :=
+		SendByte (Connection, $08) and
+		SendByte (Connection, $56) and
+		SendByte (Connection, $00) and
+		SendByte (Connection, $00);
+end;
+
+function SendWait(var Connection: TLinkConnection): Boolean; 
+begin
+	Result :=
+		SendByte (Connection, $08) and
+		SendByte (Connection, $09) and
+		SendByte (Connection, $00) and
+		SendByte (Connection, $00);
+end;
+
+function SendByte(var Connection: TLinkConnection; Value: Byte; CheckSum: PWord = nil): Boolean;
+var
+	I: Cardinal;
+	StartTime: Cardinal;
+	RetryCount: Integer;
+	State: Cardinal;
+begin
+	Result := OpenConnection (Connection);
+	if Result then begin
+		{$IFDEF LOGLINK}
+			if not LogSend then begin
+				WriteLn (LogFile);
+				WriteLn (LogFile, 'Sending:');
+				LogSend := True;
+			end;
+			Write (LogFile, ' ' + IntToHex (Value, 2));
+		{$ENDIF}
+		if Connection.CableType = lcGray then
+			Result := WriteFile (Connection.PortHandle, Value, 1, I, nil)
+		else begin
+			StartTime := GetTickCount;
+			for I := 0 to 7 do begin
+				for RetryCount := 0 to SendRetry do begin
+					if ((Value and (1 shl I)) <> 0) then
+						SetPortState (Connection.PortHandle, 2)
+					else
+						SetPortState (Connection.PortHandle, 1);
+					repeat
+						State := GetPortState (Connection.PortHandle);
+						if GetTickCount - StartTime > SendTimeout then
+							Break;
+					until State = 0;
+					if State = 0 then
+						break;
+				end;
+				if State <> 0 then begin
+					Result := False;
+					Exit;
+				end;
+				for RetryCount := 0 to SendRetry do begin
+					SetPortState (Connection.PortHandle, 3);
+					repeat
+						State := GetPortState (Connection.PortHandle);
+						if GetTickCount - StartTime > SendTimeout then
+							Break;
+					until State = 3;
+					if State = 3 then
+						break;
+				end;
+				if State <> 3 then begin
+					Result := False;
+					Exit;
+				end;
+			end;
+		end;
+		if Assigned (CheckSum) then
+			Inc (CheckSum^, Value);
+	end;
+end;
+
+function SendWord(var Connection: TLinkConnection; Value: Word; CheckSum: PWord = nil): Boolean; 
+begin
+	Result :=
+		SendByte (Connection, Value, CheckSum) and
+		SendByte (Connection, (Value shr (SizeOf (Value) * 4)), CheckSum);
+end;
+
+function SendLongWord(var Connection: TLinkConnection; Value: LongWord; CheckSum: PWord = nil): Boolean; 
+begin
+	Result :=
+		SendWord (Connection, Value, CheckSum) and
+		SendWord (Connection, (Value shr (SizeOf (Value) * 4)), CheckSum);
+end;
+
+function SendString(var Connection: TLinkConnection; Value: PChar; CheckSum: PWord = nil): Boolean;
+begin
+	Result := True;
+	while Value [0] <> #0 do begin
+		Result := Result and SendByte (Connection, Byte (Value [0]), CheckSum);
+		Value := @(Value[1]);
+	end;
+end;
+
+function SendKey(var Connection: TLinkConnection; Key: Char): Boolean;  overload;
+begin
+	Result :=
+		SendByte (Connection, $09) and
+		SendByte (Connection, $87) and
+		SendWord (Connection, Byte (Key)) and
+		WaitForAck (Connection);
+end;
+
+function SendKey(var Connection: TLinkConnection; Key: Word): Boolean;  overload;
+begin
+	Result :=
+		SendByte (Connection, $09) and
+		SendByte (Connection, $87) and
+		SendWord (Connection, Key) and
+		WaitForAck (Connection);
+end;
+
+function SendKeys(var Connection: TLinkConnection; const Keys: string): Boolean;
+var
+	I: Integer;
+begin
+	Result := OpenConnection (Connection);
+	for I := 1 to Length (Keys) do begin
+		Result := SendKey (Connection, Keys [I]);
+		if not Result then
+			Break;
+	end;
+end;
+
+function SendVar(var Connection: TLinkConnection; Folder, Name: PChar; Buffer: Pointer; BufSize: Cardinal; Progress: PDWord = nil; ProgressCallBack: TProgressCallBack = nil; ID: Pointer = nil): Boolean;
+var
+	I: Cardinal;
+	Buf: PByteArray;
+	FileType: Byte;
+	FileSize,
+	BlockSize: Word;
+	Sum: Word;
+	TempProgress: DWord;
+	StartTime: Cardinal;
+begin
+	Result := BufSize >= 88;
+	if not Result then
+		Exit;
+	if not Assigned (Progress) then
+		Progress := @TempProgress;
+	Buf := Buffer;
+	FileType := Buf [72];
+	Buf [72] := 0;
+	FileSize := Buf [86] shl 8 + Buf [87] + 2;
+	if not Assigned (Folder) then
+		Folder := @(Buf[10]);
+	Folder [8] := #0;
+	if not Assigned (Name) then
+		Name := @(Buf[64]);
+	Name [8] := #0;
+	{$IFDEF LOGLINK}
+		WriteLn (LogFile);
+		WriteLn (LogFile);
+		WriteLn (LogFile, AnsiString (Folder), '\', AnsiString (Name), ': ', FileSize, ' (', IntToHex (FileSize, 4), ') Bytes');
+	{$ENDIF}
+	Sum := 0;
+	StartTime := GetTickCount;
+	repeat until CalcReady (Connection) or (GetTickCount - StartTime > SendVarTimeout);
+	Result :=
+		SendKey (Connection, 264) and
+		SendKey (Connection, 264) and
+		SendKey (Connection, 277) and
+		SendByte (Connection, $08) and
+		SendByte (Connection, $06) and
+		SendWord (Connection, StrLen (Folder) + StrLen (Name) + 8) and
+		SendLongWord (Connection, FileSize, @Sum) and
+		SendByte (Connection, FileType, @Sum) and
+		SendByte (Connection, StrLen (Folder) + StrLen (Name) + 1, @Sum) and
+		SendString (Connection, Folder, @Sum) and
+		SendString (Connection, '\', @Sum) and
+		SendString (Connection, Name, @Sum) and
+		SendByte (Connection, $00) and
+		SendWord (Connection, Sum) and
+		WaitForAck (Connection) and
+		CalcWaiting (Connection) and
+		SendAck (Connection) and
+		SendByte (Connection, $08) and
+		SendByte (Connection, $15) and
+		SendWord (Connection, FileSize + 4) and
+		SendLongWord (Connection, 0);
+	if not Result then
+		Exit;
+	BlockSize := FileSize - 2;
+	Sum := 0;
+	Result :=
+		SendByte (Connection, BlockSize and $FF00 shr 8, @Sum) and
+		SendByte (Connection, BlockSize and $00FF, @Sum);
+	Inc (Progress^, 2);
+	if not Result then
+		Exit;
+	for I := 0 to BlockSize - 1 do begin
+		if (I < BufSize) and SendByte (Connection, Buf [I + 88], @Sum) then
+			Inc (Progress^)
+		else begin
+			Result := False;
+			Break;
+		end;
+		if ((I + 2) mod ProgressInterval = 0) and Assigned (ProgressCallBack) and (not ProgressCallBack (ID, Progress)) then begin
+			Result := False;
+			Break;
+		end;
+	end;
+	if not Result then
+		Exit;
+	Result :=
+		SendWord (Connection, Sum) and
+		WaitForAck (Connection) and
+		SendByte (Connection, $08) and
+		SendByte (Connection, $92) and
+		SendByte (Connection, $00) and
+		SendByte (Connection, $00) and
+		WaitForAck (Connection);
+end;
+
+function SendFile(var Connection: TLinkConnection; Folder, Name: PChar; const FileName: string; Progress: PDWord = nil; ProgressCallBack: TProgressCallBack = nil; ID: Pointer = nil): Boolean;
+var
+	FHandle: HFile;
+	Buffer: Pointer;
+	Size,
+	Read: Cardinal;
+begin
+	FHandle := CreateFile (PChar (FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
+	Result := FHandle <> 0;
+	if not Result then
+		Exit;
+	Size := GetFileSize (FHandle, nil);
+	Buffer := AllocMem (Size);
+	Result := Assigned (Buffer);
+	if not Result then begin
+		CloseHandle (FHandle);
+		Exit;
+	end;
+	Result := ReadFile (FHandle, Buffer^, Size, Read, nil);
+	CloseHandle (FHandle);
+	if Result then
+		Result := SendVar (Connection, Folder, Name, Buffer, Size, Progress, ProgressCallBack, ID);
+	FreeMem (Buffer);
+end;
+
+function CheckFileFormat(var Connection: TLinkConnection; const FileName: string; Folder: PChar = nil; Name: PChar = nil; Size: PWord = nil): Boolean;
+var
+	FHandle: HFile;
+	Buffer: array [0..4] of Char;
+	Read: Cardinal;
+begin
+	FHandle := CreateFile (PChar (FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
+	Result :=
+		(FHandle <> 0) and
+		ReadFile (FHandle, Buffer, 4, Read, nil);
+	if not Result then
+		Exit;
+	Buffer [4] := #0;
+	Result := Buffer = '**TI';
+	if not Result then
+		Exit;
+	if Assigned (Folder) then begin
+		SetFilePointer (FHandle, 10, nil, FILE_BEGIN);
+		Result := ReadFile (FHandle, Folder^, 8, Read, nil) and Result;
+		Folder [8] := #0;
+	end;
+	if Assigned (Name) then begin
+		SetFilePointer (FHandle, 64, nil, FILE_BEGIN);
+		Result := ReadFile (FHandle, Name^, 8, Read, nil) and Result;
+		Name [8] := #0;
+	end;
+	if Assigned (Size) then begin
+		SetFilePointer (FHandle, 86, nil, FILE_BEGIN);
+		Result := ReadFile (FHandle, Buffer, 2, Read, nil) and Result;
+		Size^ := Byte (Buffer [0]) shl 8 + Byte (Buffer [1]) + 2;
+	end;
+	if FHandle <> 0 then
+		CloseHandle (FHandle);
+end;
+
+function ExecuteHomeLine(var Connection: TLinkConnection; const Line: string): Boolean;
+begin
+	Result :=
+		SendKey (Connection, 264) and
+		SendKey (Connection, 264) and
+		SendKey (Connection, 277) and
+		SendKey (Connection, 263) and
+		SendKey (Connection, 263) and
+		SendKeys (Connection, Line) and
+		SendKey (Connection, 13);
+end;
+
+function ReceiveByte(var Connection: TLinkConnection; out Value: Byte; CheckSum: PWord = nil): Boolean;
+var
+	I,
+	State: Cardinal;
+	StartTime: Cardinal;
+begin
+	Value := 0;
+	Result := OpenConnection (Connection);
+	if Result then begin
+		if Connection.CableType = lcGray then begin
+			StartTime := GetTickCount;
+			repeat
+				Result := ReadFile (Connection.PortHandle, Value, 1, I, nil);
+			until Result or (GetTickCount - StartTime > ReceiveTimeout);
+		end else begin
+			StartTime := GetTickCount;
+			for I := 0 to 7 do begin
+				repeat
+					State := GetPortState (Connection.PortHandle);
+					if (State = 3) and (GetTickCount - StartTime > ReceiveTimeout) then begin
+						Result := False;
+						Exit;
+					end;
+				until State <> 3;
+				if State = 1 then begin
+					Value := Value or (1 shl I);
+					SetPortState (Connection.PortHandle, 1);
+					State := 2;
+				end else begin
+					SetPortState (Connection.PortHandle, 2);
+					State := 1;
+				end;
+				while (GetPortState (Connection.PortHandle) and State) = 0 do
+					if GetTickCount - StartTime > ReceiveTimeout then begin
+						Result := False;
+						Exit;
+					end;
+				SetPortState (Connection.PortHandle, 3);
+			end;
+		end;
+		if Assigned (CheckSum) then
+			Inc (CheckSum^, Value);
+		{$IFDEF LOGLINK}
+			if LogSend then begin
+				WriteLn (LogFile);
+				WriteLn (LogFile, 'Receiving:');
+				LogSend := False;
+			end;
+			Write (LogFile, ' ' + IntToHex (Value, 2));
+		{$ENDIF}
+	end;
+end;
+
+function ReceiveWord(var Connection: TLinkConnection; out Value: Word; CheckSum: PWord = nil): Boolean;
+var
+	Temp1,
+	Temp2: Byte;
+begin
+	Result :=
+		ReceiveByte (Connection, Temp1, CheckSum) and
+		ReceiveByte (Connection, Temp2, CheckSum);
+	Value := Temp1 or (Temp2 shl (SizeOf (Temp1) * 8));
+end;
+
+function ReceiveLongWord(var Connection: TLinkConnection; out Value: LongWord; CheckSum: PWord = nil): Boolean;
+var
+	Temp1,
+	Temp2: Word;
+begin
+	Result :=
+		ReceiveWord (Connection, Temp1, CheckSum) and
+		ReceiveWord (Connection, Temp2, CheckSum);
+	Value := Temp1 or (Temp2 shl (SizeOf (Temp1) * 8));
+end;
+
+function GetCalcType(var Connection: TLinkConnection): Boolean;
+begin
+	Result := OpenConnection (Connection);
+end;
+
+function GetPortState(Handle: THandle): Cardinal;
+var
+	InternalState: Cardinal;
+begin
+	GetCommModemStatus (Handle, InternalState);
+	Result := 0;
+	if (InternalState and MS_CTS_ON) <> 0 then
+		Inc (Result, 1);
+	if (InternalState and MS_DSR_ON) <> 0 then
+		Inc (Result, 2);
+end;
+
+procedure SetPortState(Handle: THandle; State: Cardinal);
+procedure Send(Func: Cardinal);
+begin
+	EscapeCommFunction (Handle, Func);
+end;
+begin
+	if (State and 2) <> 0 then
+		Send (SETRTS)
+	else
+		Send (CLRRTS);
+	if (State and 1) <> 0 then
+		Send (SETDTR)
+	else
+		Send (CLRDTR);
+end;
+
+function GetPortName(const Port: TLinkPort): string;
+begin
+	case Port.PortType of
+		lpCOM: Result := 'COM' + IntToStr (Port.PortNumber);
+		else   Result := '';
+	end;
+end;
+
+function IsValidAck(Value: Byte): Boolean;
+begin
+	Result := Value in [$88, $89, $98];
+end;
+
+end.

BIN
tigcc/ide/MainUnit.dfm


+ 5363 - 0
tigcc/ide/MainUnit.pas

@@ -0,0 +1,5363 @@
+unit MainUnit;
+
+interface
+
+uses
+	MasterUnit, SourceFileUnit, FolderUnit, ToolsListUnit, LinkDLLUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	Menus, StdCtrls, ExtCtrls, ImgList, ComCtrls, Buttons, ActnList, ToolWin,
+	Printers, SourceEditUnit, HTMLHelpUnit, MemoComponentUnit, ScktComp;
+
+type
+	TMainForm = class(TForm)
+		ProjectTree: TTreeView;
+		LittleIcons: TImageList;
+		TreeEditorSplitter: TSplitter;
+		MainMenu: TMainMenu;
+		MainMenuFile: TMenuItem;
+		MenuFileNew: TMenuItem;
+		Project1: TMenuItem;
+		AssemblerSource1: TMenuItem;
+		Open1: TMenuItem;
+		Save1: TMenuItem;
+		SaveAs1: TMenuItem;
+		N1: TMenuItem;
+		Exit1: TMenuItem;
+		CSourceFile1: TMenuItem;
+		MainMenuEdit: TMenuItem;
+		Undo1: TMenuItem;
+		N2: TMenuItem;
+		Delete1: TMenuItem;
+		Cut1: TMenuItem;
+		Copy1: TMenuItem;
+		Paste1: TMenuItem;
+		AddFiles1: TMenuItem;
+		MenuCompileLine: TMenuItem;
+		MainMenuProject: TMenuItem;
+		Compile1: TMenuItem;
+		Link1: TMenuItem;
+		N4: TMenuItem;
+		Options1: TMenuItem;
+		AddFileDlg: TOpenDialog;
+		N5: TMenuItem;
+		Preferences1: TMenuItem;
+		N6: TMenuItem;
+		HeaderFile1: TMenuItem;
+		SourceFilePopup: TPopupMenu;
+		Compile2: TMenuItem;
+		N7: TMenuItem;
+		Remove1: TMenuItem;
+		Delete2: TMenuItem;
+		Splitter2: TSplitter;
+		ErrWinPanel: TPanel;
+		ErrorPanel: TPanel;
+		CloseErrorsButton: TSpeedButton;
+		ErrorList: TListView;
+		Label1: TLabel;
+		Label2: TLabel;
+		ErrorsLabel: TLabel;
+		WarningsLabel: TLabel;
+		Save2: TMenuItem;
+		SaveAs2: TMenuItem;
+		N8: TMenuItem;
+		MainMenuHelp: TMenuItem;
+		Build1: TMenuItem;
+		N9: TMenuItem;
+		SelectAll1: TMenuItem;
+		OpenProjectDlg: TOpenDialog;
+		SaveProjectDlg: TSaveDialog;
+		N10: TMenuItem;
+		About1: TMenuItem;
+		StatusBar: TStatusBar;
+		ToolBarImages: TImageList;
+		FileNewPopup: TPopupMenu;
+		HeaderFile2: TMenuItem;
+		Actions: TActionList;
+		ActionFileNewProject: TAction;
+		ActionFileNewCHeaderFile: TAction;
+		ActionFileNewGNUAsmHeaderFile: TAction;
+		ActionFileNewA68kAsmHeaderFile: TAction;
+		ActionFileNewCFile: TAction;
+		ActionFileNewGNUAsmFile: TAction;
+		ActionFileNewA68kAsmFile: TAction;
+		ActionFileOpen: TAction;
+		ActionFileSave: TAction;
+		ActionFileSaveAs: TAction;
+		ActionFilePreferences: TAction;
+		ActionFileExit: TAction;
+		ActionEditUndo: TAction;
+		ActionEditDelete: TAction;
+		ActionEditCut: TAction;
+		ActionEditCopy: TAction;
+		ActionEditPaste: TAction;
+		ActionEditSelectAll: TAction;
+		ActionProjectAddFiles: TAction;
+		ActionProjectCompile: TAction;
+		ActionProjectMake: TAction;
+		ActionProjectBuild: TAction;
+		ActionProjectOptions: TAction;
+		ActionHelpDocumentation: TAction;
+		ActionHelpAbout: TAction;
+		ActionTreeItemSave: TAction;
+		ActionTreeItemSaveAs: TAction;
+		ActionTreeItemCompile: TAction;
+		ActionTreeItemRemove: TAction;
+		ActionTreeItemDelete: TAction;
+		CSourceFile2: TMenuItem;
+		AssemblerSourceFile1: TMenuItem;
+		Project3: TMenuItem;
+		N11: TMenuItem;
+		ActionProjectShowErrors: TAction;
+		ErrorsandWarnings1: TMenuItem;
+		N12: TMenuItem;
+		MainMenuFind: TMenuItem;
+		ActionFindFind: TAction;
+		ActionFindReplace: TAction;
+		ActionFindOpenFile: TAction;
+		Find2: TMenuItem;
+		Replace1: TMenuItem;
+		OpenFileAtCursor1: TMenuItem;
+		N13: TMenuItem;
+		FindDlg: TFindDialog;
+		ReplaceDlg: TReplaceDialog;
+		ToolBarImagesDisabled: TImageList;
+		PrintDlg: TPrintDialog;
+		ActionFilePrint: TAction;
+		Print1: TMenuItem;
+		N14: TMenuItem;
+		ActionFilePrintQuickly: TAction;
+		ErrorListIcons: TImageList;
+		DocFile: THTMLHelp;
+		ActionHelpContents: TAction;
+		ActionHelpIndex: TAction;
+		ActionHelpSearch: TAction;
+		ActionTreeItemRename: TAction;
+		N19: TMenuItem;
+		Rename1: TMenuItem;
+		Contents1: TMenuItem;
+		Index1: TMenuItem;
+		Search1: TMenuItem;
+		EditorPopup: TPopupMenu;
+		Undo2: TMenuItem;
+		N16: TMenuItem;
+		Clear1: TMenuItem;
+		Cut2: TMenuItem;
+		Copy2: TMenuItem;
+		Paste2: TMenuItem;
+		N17: TMenuItem;
+		SelectAll2: TMenuItem;
+		MainToolBar: TToolBar;
+		ToolBarNewButton: TToolButton;
+		ToolButton2: TToolButton;
+		ToolButton3: TToolButton;
+		ToolButton4: TToolButton;
+		ToolButton23: TToolButton;
+		ToolButton24: TToolButton;
+		ToolButton6: TToolButton;
+		ToolButton7: TToolButton;
+		ToolButton8: TToolButton;
+		ToolButton9: TToolButton;
+		ToolButton10: TToolButton;
+		ToolButton5: TToolButton;
+		ToolButton11: TToolButton;
+		ToolButton20: TToolButton;
+		ToolButton21: TToolButton;
+		ToolBarCompileLine1: TToolButton;
+		ToolBarCompileButton: TToolButton;
+		ToolButton15: TToolButton;
+		ToolBarCompileLine2: TToolButton;
+		ToolButton18: TToolButton;
+		ToolButton19: TToolButton;
+		ActionEditRedo: TAction;
+		Redo1: TMenuItem;
+		Redo2: TMenuItem;
+		EditorPanel: TPanel;
+		NoEditor: TPanel;
+		FunctionPopup: TPopupMenu;
+		ActionFindFunctions: TAction;
+		N15: TMenuItem;
+		Functions1: TMenuItem;
+		ToolButton25: TToolButton;
+		NoFunctionsItem: TMenuItem;
+		ActionFileNewTextFile: TAction;
+		TextFile1: TMenuItem;
+		TextFile2: TMenuItem;
+		ActionEditIncreaseIndent: TAction;
+		ActionEditDecreaseIndent: TAction;
+		N18: TMenuItem;
+		IncreaseIndent1: TMenuItem;
+		DecreaseIndent1: TMenuItem;
+		N20: TMenuItem;
+		IncreaseIndent2: TMenuItem;
+		DecreaseIndent2: TMenuItem;
+		N21: TMenuItem;
+		OpenFileatCursor2: TMenuItem;
+		GNUAssemblySourceFile1: TMenuItem;
+		GNUAssemblySourceFile2: TMenuItem;
+		ActionFileNewQuillFile: TAction;
+		QuillSourceFile1: TMenuItem;
+		QuillSourceFile2: TMenuItem;
+		ActionProjectStopCompilation: TAction;
+		ActionProjectForceQuitCompiler: TAction;
+		ToolButton16: TToolButton;
+		ToolButton17: TToolButton;
+		StopCompilation1: TMenuItem;
+		ForceQuitCompiler1: TMenuItem;
+		ActionHelpNews: TAction;
+		N3: TMenuItem;
+		News1: TMenuItem;
+		ActionDebugRun: TAction;
+		ActionDebugPause: TAction;
+		ActionDebugReset: TAction;
+		MainMenuDebug: TMenuItem;
+		Run1: TMenuItem;
+		N22: TMenuItem;
+		Pause1: TMenuItem;
+		Reset1: TMenuItem;
+		ToolBarRunButton: TToolButton;
+		ToolBarDebugLine: TToolButton;
+		ToolBarPauseButton: TToolButton;
+		ToolButton12: TToolButton;
+		ToolButton13: TToolButton;
+		ChangeNotificationTimer: TTimer;
+		ToolBarBevel: TBevel;
+		ToolBarEndLine: TToolButton;
+		RecentFilesLine: TMenuItem;
+		RecentFilesPopup: TPopupMenu;
+		NoFilesItem: TMenuItem;
+		ActionToolsConfigure: TAction;
+		MainMenuTools: TMenuItem;
+		Configure1: TMenuItem;
+		ToolsLine: TMenuItem;
+		ActionProjectShowProgramOutput: TAction;
+		ProgramOutput1: TMenuItem;
+		ActionFileNewFolder: TAction;
+		N23: TMenuItem;
+		Folder1: TMenuItem;
+		N24: TMenuItem;
+		Folder2: TMenuItem;
+		FolderPopup: TPopupMenu;
+    MenuItem6: TMenuItem;
+    MenuItem9: TMenuItem;
+    CategoryPopup: TPopupMenu;
+		ActionFileNewFile: TAction;
+    File1: TMenuItem;
+    Folder3: TMenuItem;
+    N25: TMenuItem;
+    Folder4: TMenuItem;
+    File2: TMenuItem;
+    ActionTreeItemNewFolder: TAction;
+    ActionTreeItemNewFile: TAction;
+		GNUAssemblyHeaderFile1: TMenuItem;
+		GNUAssemblyHeaderFile2: TMenuItem;
+		A68kAssemblyHeaderFile1: TMenuItem;
+    A68kAssemblyHeaderFile2: TMenuItem;
+		procedure FormCreate(Sender: TObject);
+		procedure FormDestroy(Sender: TObject);
+		procedure AppException(Sender: TObject; E: Exception);
+		procedure ProjectTreeEditing(Sender: TObject; Node: TTreeNode;
+			var AllowEdit: Boolean);
+		procedure ProjectAddFiles(Sender: TObject);
+		procedure ProjectTreeChange(Sender: TObject; Node: TTreeNode);
+		procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+		procedure ProjectTreeDeletion(Sender: TObject; Node: TTreeNode);
+		procedure FileExit(Sender: TObject);
+		procedure FileNewProject(Sender: TObject);
+		procedure TreeItemRemove(Sender: TObject);
+		procedure TreeItemDelete(Sender: TObject);
+		procedure TreeItemCompile(Sender: TObject);
+		procedure CloseErrorsButtonClick(Sender: TObject);
+		procedure ErrorListDeletion(Sender: TObject; Item: TListItem);
+		procedure TreeItemSave(Sender: TObject);
+		procedure HelpDocumentation(Sender: TObject);
+		procedure EditorEnter(Sender: TObject);
+		procedure EditorExit(Sender: TObject);
+		procedure EditUndo(Sender: TObject);
+		procedure EditRedo(Sender: TObject);
+		procedure EditClear(Sender: TObject);
+		procedure EditCut(Sender: TObject);
+		procedure EditCopy(Sender: TObject);
+		procedure EditPaste(Sender: TObject);
+		procedure EditSelectAll(Sender: TObject);
+		procedure ProjectCompile(Sender: TObject);
+		procedure ProjectMake(Sender: TObject);
+		procedure FileOpenProject(Sender: TObject);
+		procedure FileSaveAll(Sender: TObject);
+		procedure FileSaveProjectAs(Sender: TObject);
+		procedure EditorKeyDown(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure ProjectBuild(Sender: TObject);
+		procedure ProjectTreeKeyDown(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure ProjectTreeMouseUp(Sender: TObject; Button: TMouseButton;
+			Shift: TShiftState; X, Y: Integer);
+		procedure ProjectTreeEdited(Sender: TObject; Node: TTreeNode;
+			var S: String);
+		procedure ProjectOptions(Sender: TObject);
+		procedure FilePreferences(Sender: TObject);
+		procedure FileNewHeaderFile(Sender: TObject);
+		procedure FileNewCSourceFile(Sender: TObject);
+		procedure FileNewGNUAssemblerSourceFile(Sender: TObject);
+		procedure FileNewAssemblerSourceFile(Sender: TObject);
+		procedure FileNewQuillSourceFile(Sender: TObject);
+		procedure FileNewTextFile(Sender: TObject);
+		procedure TreeItemSaveAs(Sender: TObject);
+		procedure HelpAbout(Sender: TObject);
+		procedure DisplayHint(Sender: TObject);
+		procedure ShowHideErrors(Sender: TObject);
+		procedure FindString(Sender: TObject; AllFiles: Boolean);
+		procedure ReplaceDlgReplace(Sender: TObject);
+		procedure FindText(Sender: TObject);
+		procedure ReplaceText(Sender: TObject);
+		procedure FindOpenFile(Sender: TObject);
+		procedure FindDlgFind(Sender: TObject);
+		procedure ActionsExecute(Action: TBasicAction; var Handled: Boolean);
+		procedure ProjectTreeEnter(Sender: TObject);
+		procedure ProjectTreeExit(Sender: TObject);
+		procedure ProjectTreeChanging(Sender: TObject; Node: TTreeNode;
+			var AllowChange: Boolean);
+		procedure EditorChange(Sender: TObject);
+		procedure FilePrint(Sender: TObject);
+		procedure FilePrintQuickly(Sender: TObject);
+		procedure TreeItemRename(Sender: TObject);
+		procedure HelpContents(Sender: TObject);
+		procedure HelpIndex(Sender: TObject);
+		procedure HelpSearch(Sender: TObject);
+		procedure SplitterMoved(Sender: TObject);
+		procedure ProjectTreeMouseDown(Sender: TObject; Button: TMouseButton;
+			Shift: TShiftState; X, Y: Integer);
+		procedure ToolBarManagerBandMove(Sender: TObject; Control: TControl;
+			var ARect: TRect);
+		procedure ProjectTreeDragOver(Sender, Source: TObject; X, Y: Integer;
+			State: TDragState; var Accept: Boolean);
+		procedure ProjectTreeDragDrop(Sender, Source: TObject; X, Y: Integer);
+		procedure ErrorListClick(Sender: TObject);
+		procedure DeleteError(Sender: TObject);
+		procedure FunctionPopupPopup(Sender: TObject);
+		procedure FindFunctions(Sender: TObject);
+		procedure FindFunctionFromPopup(Sender: TObject);
+		procedure IncreaseIndent(Sender: TObject);
+		procedure DecreaseIndent(Sender: TObject);
+		procedure ProjectStopCompilation(Sender: TObject);
+		procedure ProjectForceQuitCompiler(Sender: TObject);
+		procedure HelpNews(Sender: TObject);
+		procedure DebugRun(Sender: TObject);
+		procedure DebugPause(Sender: TObject);
+		procedure DebugReset(Sender: TObject);
+		procedure FormKeyDown(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure ChangeNotificationTick(Sender: TObject);
+		procedure RecentFileClick(Sender: TObject);
+		procedure ToolsConfigure(Sender: TObject);
+		procedure ToolClick(Sender: TObject);
+		procedure ProjectTreeStartDrag(Sender: TObject;
+			var DragObject: TDragObject);
+		procedure ShowProgramOutput(Sender: TObject);
+		procedure FileNewFolder(Sender: TObject);
+    procedure FileNewFile(Sender: TObject);
+    procedure ErrorListKeyDown(Sender: TObject; var Key: Word;
+      Shift: TShiftState);
+	private
+		EditorToHide: TWinControl;
+		TempLockHandle: THandle;
+		FModified: Boolean;
+		FInvalidated: Boolean;
+		FProjectFile: string;
+		InChangeNotification: Boolean;
+		procedure WMDropFiles(var Msg: TMessage); message WM_DROPFILES;
+		procedure SetProjectFile(const Value: string);
+		procedure SetModified(const Value: Boolean);
+		function GetCurrentEditor: TMemoComponent;
+		function GetInvalidated: Boolean;
+	public
+		TopNode: TTreeNode;
+		OriginalCaption: string;
+		LinkLibHandle: HModule;
+		LinkLibGetInterfaceVersion: TLinkLibGetInterfaceVersion;
+		LinkLibLinkFiles: TLinkLibLinkFiles;
+		LinkLibCreateArchive: TLinkLibCreateArchive;
+		SourceFiles: TSourceFiles;
+		JumpToError,
+		OpenFolderMessage,
+		AutoSave,
+		DeleteErrors,
+		StartingAppNow,
+		OpeningProjectNow,
+		NoHideEditor: Boolean;
+		PreviousNode: TTreeNode;
+		SyntaxCBackup: TSyntaxColoring;
+		SyntaxAsmGNUBackup: TSyntaxColoring;
+		SyntaxAsmBackup: TSyntaxColoring;
+		SyntaxQuillBackup: TSyntaxColoring;
+		Closing: Boolean;
+		ProgSize: Integer;
+		OptimizeInfo: TLinkLibOptimizeInfo;
+		Funcs: TSourceFileFunctions;
+		CurrentStrings: TMemoryStream;
+		CurVTIType: TCurVTIType;
+		RecentFiles: TStringList;
+		ToolsList: TToolsList;
+		property ProjectFile: string read FProjectFile write SetProjectFile;
+		property Modified: Boolean read FModified write SetModified;
+		property Invalidated: Boolean read GetInvalidated write FInvalidated;
+		property CurrentEditor: TMemoComponent read GetCurrentEditor;
+		procedure Modify;
+		procedure WarnIfModified;
+		procedure FileNew;
+		procedure FileClear;
+		procedure FileLoad;
+		procedure FileOpen(const FN: string);
+		procedure FileSave;
+		procedure FileSaveAs(const FN: string);
+		procedure ResetProjectSettings;
+		procedure AppCompStartFile;
+		procedure AppCompStop;
+		procedure AppCompSetMessage(const Msg: string);
+		procedure AppCompUpdate;
+		procedure UpdateProgramOutput;
+		procedure CopyHeaders;
+		procedure DeleteHeaders;
+		procedure ClearErrors;
+		procedure HideErrors;
+		procedure ShowErrors;
+		procedure UpdateErrorWindow;
+		procedure AddError(const Line: string; BugTp: TBugType; SourceF: string; ErrFunc: string; ErrMessage: string; SourceLn: Integer; Offset: Integer);
+		procedure CompileProject;
+		procedure MakeFileWrapped;
+		procedure MakeFile;
+		function AddSourceFile(const FN: string; OpenOnly: Boolean = False; SourceFileClass: TSourceFileClass = nil; Folder: TFolder = nil): TSourceFile;
+		function GetNewFileName(const FolderPath, Ext: string): string;
+		procedure LoadPreferences;
+		procedure SavePreferences;
+		procedure BeginCompilation;
+		procedure EndCompilation;
+		procedure RecompileFiles;
+		procedure UpdateEditButtons;
+		procedure UpdateStatusBar;
+		procedure UpdateFuncs;
+		procedure UpdateDebugSettings;
+		procedure SortFiles;
+		procedure DisplayFolderMessage;
+		procedure ClearDebugInfo;
+		function GetVTIWindow: HWnd;
+		procedure SendFiles(FNList: array of string);
+		procedure ExecuteCommandLine(const Line: string);
+		procedure SelectNode(Node: TTreeNode);
+		procedure AddToRecent(const FileName: string);
+		procedure UpdateRecent;
+		procedure AddTool(const Title, CommandLine, WorkingDir: string; WindowState: TWindowState);
+		function GetSourceTypeFolder(Node: TTreeNode): TTreeNode;
+		function FindFileInsertionPoint(ParentNode: TTreeNode): TTreeNode;
+		function CreateFileNode(ParentNode: TTreeNode; SourceFile: TSourceFile): TTreeNode;
+		function GetSelectedFolder(SourceClass: TSourceFileClass): TFolder;
+{$IFDEF CODINGEXT}
+		procedure InitCodingExt;
+		procedure ActionFindSymbolExecute(Sender: TObject);
+{$ENDIF}
+	end;
+
+var
+	MainForm: TMainForm;
+
+type
+	TRecentFileMenuItem = class(TObject)
+		FileMenuItem: TMenuItem;
+		PopupMenuItem: TMenuItem;
+	public
+		destructor Destroy; override;
+	end;
+
+const
+	MaxRecentFiles = 4;
+
+type
+	TNoImageDragObject = class(TDragControlObject)
+	public
+		function GetDragImages: TDragImageList; override;
+		procedure HideDragImage; override;
+		procedure ShowDragImage; override;
+	end;
+
+procedure LinkLibError(FileName, Text: PChar; MessageType: LongInt); cdecl;
+function LinkLibGetOutputFile(var DestFile: TLinkLibDestFile; FileSize, DestCalc, FileRole, FileFormat, FileType: LongInt; Extension: PChar; Executable: WordBool; var EffectiveSize: LongInt): WordBool; cdecl;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	CalcUnit, ParsingUnit, ProcessUnit,
+	StartupScreenUnit, PreferencesUnit, ProjectOptionsUnit,
+	AboutUnit, SourceFileWinUnit, FunctionsWinUnit,
+	OpenFileStatusUnit, NewsUnit, SendProgressUnit, ToolsUnit,
+	ProgramOutputUnit, VTIStartUnit,
+	LinkUnit,
+	UtilsDos, UtilsWin, HandleWaitThreadUnit, FileReadToBufferThreadUnit,
+	ShellAPI, ShlObj, IniFiles, Registry, WinSpool, ClipBrd{$IFDEF CODINGEXT}, CompletionForm{$ENDIF};
+
+const
+	RegKey = '\Software\SeReSoft\TI-GCC IDE';
+
+type
+	TFileRole = (frMain, frData);
+	TLinkOutputFile = record
+		Data: TMemoryStream;
+		Tag: Byte;
+		VarExt: string;
+		ExeFile,
+		OSUpgrade: Boolean;
+	end;
+
+var
+	ProcID: Cardinal;
+	SendWin: HWnd;
+	LinkOutputFiles: array [TCalcDest, TFileRole] of TLinkOutputFile;
+
+function EnumWindowsFunc(Win: HWnd; Param: Integer): Bool; stdcall;
+var
+	Name: array [0..32] of Char;
+	NewProcID: DWord;
+begin
+	Result := True;
+	GetWindowThreadProcessID (Win, @NewProcID);
+	if NewProcID = ProcID then begin
+		GetClassName (Win, Name, 32);
+		if Name = '#32770' then begin
+			Result := False;
+			SendWin := Win;
+		end;
+	end;
+end;
+
+procedure ErrorMessage(const Msg: string);
+begin
+	if UpperCase (Copy (Msg, 1, Length ('ERROR:'))) = 'ERROR:' then
+		MainForm.AddError (Msg, btError, '', '', Trim (Copy (Msg, Length ('ERROR:') + 1, Length (Msg))), 0, 0)
+	else if UpperCase (Copy (Msg, 1, Length ('WARNING:'))) = 'WARNING:' then
+		MainForm.AddError (Msg, btWarning, '', '', Trim (Copy (Msg, Length ('WARNING:') + 1, Length (Msg))), 0, 0);
+end;
+
+procedure LinkLibError(FileName, Text: PChar; MessageType: LongInt); cdecl;
+var
+	BugTp: TBugType;
+	ErrorLine: string;
+begin
+	if MessageType = llmtError then
+		BugTp := btError
+	else
+		BugTp := btWarning;
+	ErrorLine := StringReplace (StrPas (Text), '`', '''', [rfReplaceAll]);
+	MainForm.AddError (ErrorLine, BugTp, FileName, '', ErrorLine, 0, 0);
+end;
+
+function LinkLibGetOutputFile(var DestFile: TLinkLibDestFile; FileSize, DestCalc, FileRole, FileFormat, FileType: LongInt; Extension: PChar; Executable: WordBool; var EffectiveSize: LongInt): WordBool; cdecl;
+var
+	CalcDest: TCalcDest;
+	CalcFileRole: TFileRole;
+begin
+	Result := False;
+	case FileFormat of
+		llffTIOS:
+			EffectiveSize := 2 + FileSize + 1;
+		llffTIOSUpgrade:
+			EffectiveSize := FileSize + SizeOf (TCalcOSFooter);
+		else
+			Exit;
+	end;
+	case DestCalc of
+		llcdTI89:                     CalcDest := cdTI89;
+		llcdTI89 or llcdFlagTitanium: CalcDest := cdTI89Titanium;
+		llcdTI92Plus:                 CalcDest := cdTI92Plus;
+		llcdV200:                     CalcDest := cdV200;
+		llcdTI92:                     CalcDest := cdTI92;
+		else
+			Exit;
+	end;
+	case FileRole of
+		llfrMain: CalcFileRole := frMain;
+		llfrData: CalcFileRole := frData;
+		else
+			Exit;
+	end;
+	with LinkOutputFiles [CalcDest, CalcFileRole] do begin
+		if not Assigned (Data) then
+			Data := TMemoryStream.Create;
+		Data.Size := FileSize;
+		DestFile.Data := Data.Memory;
+		Tag := FileType;
+		if Assigned (Extension) then begin
+			VarExt := Extension;
+			Inc (EffectiveSize, Length (VarExt) + 2);
+		end else
+			VarExt := '';
+		ExeFile := Executable;
+		OSUpgrade := (FileFormat = llffTIOSUpgrade);
+	end;
+	Result := True;
+end;
+
+{ TRecentFileMenuItem }
+
+destructor TRecentFileMenuItem.Destroy;
+begin
+	FileMenuItem.Free;
+	PopupMenuItem.Free;
+	inherited;
+end;
+
+{ TNoImageDragObject }
+
+function TNoImageDragObject.GetDragImages: TDragImageList;
+begin
+	Result := nil;
+end;
+
+procedure TNoImageDragObject.HideDragImage;
+begin
+end;
+
+procedure TNoImageDragObject.ShowDragImage;
+begin
+end;
+
+{ TMainForm }
+
+procedure TMainForm.Modify;
+begin
+	Modified := True;
+end;
+
+procedure TMainForm.FormCreate(Sender: TObject);
+var
+	TempDir: array [0..255] of Char;
+	S: string;
+	TempLockData: TWin32FindData;
+begin
+	StartingAppNow := True;
+	try
+		if Assigned (StartupScreenForm) then
+			StartupScreenForm.DisplayText := 'Setting Up Environment...';
+		Application.OnException := AppException;
+		WindowState := wsMaximized;
+		RecentFiles := TStringList.Create;
+		ToolsList := TToolsList.Create (Self, TToolsListItem);
+		TIGCCFolder := ExtractFilePath (ParamStr (0));
+		Delete (TIGCCFolder, Pos (UpperCase (IDELocation), UpperCase (TIGCCFolder)), Length (TIGCCFolder));
+		with TRegistry.Create do try
+			RootKey := HKey_Local_Machine;
+			if OpenKeyReadOnly ('\Software\TIGCC Team\TIGCC') then try
+				if ValueExists ('Program Folder') then
+					TIGCCFolder := ReadString ('Program Folder');
+			except end;
+		finally
+			Free;
+		end;
+		try
+			if FileExists (WithBackslash (TIGCCFolder) + A68kLocation + 'A68k.exe') then
+				Include (SpecialSupport, ssA68k);
+		except end;
+		try
+			if FileExists (WithBackslash (TIGCCFolder) + QuillIncludeLocation + 'Quill.drv')
+				or FileExists (WithBackslash (TIGCCFolder) + CIncludeLocation + 'Quill.drv')
+				or FileExists (WithBackslash (TIGCCFolder) + GCCLocation + 'Quill.drv') then
+				Include (SpecialSupport, ssQuill);
+		except end;
+		try
+			if FileExists (WithBackslash (TIGCCFolder) + PackLocation + 'Pack.exe') then
+				Include (SpecialSupport, ssPack);
+		except end;
+		try
+			if FileExists (WithBackslash (TIGCCFolder) + StdLibLocation + 'flashos.a') then
+				Include (SpecialSupport, ssFlashOS);
+		except end;
+		try
+			if FileExists (WithBackslash (TIGCCFolder) + StdLibLocation + 'fargo.a') then
+				Include (SpecialSupport, ssFargo);
+		except end;
+		CompStartFile := AppCompStartFile;
+		CompStop := AppCompStop;
+		CompSetMessage := AppCompSetMessage;
+		CompUpdate := AppCompUpdate;
+		CompUpdateProgramOutput := UpdateProgramOutput;
+		LinkLibHandle := LoadLibrary (PChar (WithBackslash (TIGCCFolder) + LinkLibLocation + 'Link.dll'));
+		if LinkLibHandle <> 0 then begin
+			LinkLibGetInterfaceVersion := GetProcAddress (LinkLibHandle, 'GetInterfaceVersion');
+			if Assigned (LinkLibGetInterfaceVersion) and (LinkLibGetInterfaceVersion = LinkLibCurInterfaceVersion) then begin
+				LinkLibLinkFiles := GetProcAddress (LinkLibHandle, 'LinkFiles');
+				LinkLibCreateArchive := GetProcAddress (LinkLibHandle, 'CreateArchive');
+			end;
+		end;
+		SourceFiles := TSourceFiles.Create;
+		SyntaxCBackup := TSyntaxColoring.Create (nil);
+		SyntaxCBackup.Assign (SyntaxC);
+		SyntaxAsmGNUBackup := TSyntaxColoring.Create (nil);
+		SyntaxAsmGNUBackup.Assign (SyntaxAsmGNU);
+		SyntaxAsmBackup := TSyntaxColoring.Create (nil);
+		if ssA68k in SpecialSupport then
+			SyntaxAsmBackup.Assign (SyntaxAsm);
+		SyntaxQuillBackup := TSyntaxColoring.Create (nil);
+		if ssQuill in SpecialSupport then
+			SyntaxQuillBackup.Assign (SyntaxQuill);
+		TopNode := ProjectTree.Items.Item [0];
+		SourceFileUnit.AppNode := TopNode;
+		SourceFileUnit.NoEditor := NoEditor;
+		OriginalCaption := Caption;
+		Application.OnHint := DisplayHint;
+		if ssA68k in SpecialSupport then begin
+			ActionFileNewA68kAsmHeaderFile.Visible := True;
+			ActionFileNewA68kAsmFile.Visible := True;
+			with ProjectTree.Items.Insert (TopNode.Item [TAsmSourceFile.GetClassTreeIndex], 'A68k Assembly Files') do begin
+				ImageIndex    := TopNode.Item[0].ImageIndex;
+				SelectedIndex := TopNode.Item[0].SelectedIndex;
+			end;
+		end;
+		if ssQuill in SpecialSupport then begin
+			ActionFileNewQuillFile.Visible := True;
+			S := OpenProjectDlg.Filter;
+			Insert (TQuillSourceFile.GetClassFilter + '|', S, Pos (TNormalTextSourceFile.GetClassFilter, S));
+			while Pos ('*.asm;*.txt', S) > 0 do
+				Insert (';*.qll', S, Pos ('*.asm;*.txt', S) + Length ('*.asm'));
+			OpenProjectDlg.Filter := S;
+			OpenProjectDlg.FilterIndex := OpenProjectDlg.FilterIndex + 1;
+			S := AddFileDlg.Filter;
+			Insert (TQuillSourceFile.GetClassFilter + '|', S, Pos (TObjectSourceFile.GetClassFilter, S));
+			while Pos ('*.asm;*.o', S) > 0 do
+				Insert (';*.qll', S, Pos ('*.asm;*.o', S) + Length ('*.asm'));
+			AddFileDlg.Filter := S;
+			AddFileDlg.FilterIndex := AddFileDlg.FilterIndex + 1;
+			with ProjectTree.Items.Insert (TopNode.Item [TQuillSourceFile.GetClassTreeIndex], 'Quill Files') do begin
+				ImageIndex    := TopNode.Item[0].ImageIndex;
+				SelectedIndex := TopNode.Item[0].SelectedIndex;
+			end;
+		end;
+		ProjectTree.FullExpand;
+		ResetProjectSettings;
+		AssumeUndefined := False;
+		AutoSave := True;
+		AutoNews := False;
+		LastNewsDate := 0;
+		GetTempPath (SizeOf (TempDir), TempDir);
+		Temp := AnsiString (TempDir);
+		if (Length (Temp) <= 0) or (not DirExists (Temp)) then begin
+			GetEnvironmentVariable ('TMP', TempDir, SizeOf (TempDir));
+			Temp := AnsiString (TempDir);
+		end;
+		if (Length (Temp) <= 0) or (not DirExists (Temp)) then begin
+			GetEnvironmentVariable ('TEMP', TempDir, SizeOf (TempDir));
+			Temp := AnsiString (TempDir);
+		end;
+		if (Length (Temp) <= 0) or (Length (Temp) > 30) or (Pos (' ', Temp) > 0) or (Pos ('TEMP', UpperCase (Temp)) <= 0) then begin
+			GetWindowsDirectory (TempDir, SizeOf (TempDir));
+			Temp := WithBackslash (AnsiString (TempDir)) + 'TEMP\';
+			if not DirExists (Temp) then try
+				MkDir (Temp);
+			except end;
+		end;
+		if (Length (Temp) <= 0) or (Length (Temp) > 30) or (Pos (' ', Temp) > 0) then begin
+			Temp := 'C:\TEMP\';
+			if not DirExists (Temp) then try
+				MkDir (Temp);
+			except end;
+		end;
+		Temp := WithBackslash (Temp) + IntToHex (GetCurrentProcessID, 8) + '\';
+		if not DirExists (Temp) then try
+			MkDir (Temp);
+		except end;
+		TempLockHandle := Windows.FindFirstFile (PChar (Temp + '*.*'), TempLockData);
+		StopOnErrors := False;
+		JumpToError := True;
+		OpenFolderMessage := True;
+		DeleteAssemblyFiles := True;
+		DeleteObjectFiles := False;
+{$IFDEF CanSplit}
+		SplitFiles := True;
+{$ENDIF}
+		DeleteErrors := True;
+		TransferTarget := ttVTI;
+		LinkPort.PortType := lpCOM;
+		LinkPort.PortNumber := 1;
+		LinkCable := lcBlack;
+		TabSizeAsm := 8;
+		TabSizeC := 2;
+		AutoBlocks := True;
+		EditorOnFly := True;
+		EditorDragDrop := True;
+		if Assigned (StartupScreenForm) then
+			StartupScreenForm.DisplayText := 'Loading Preferences...';
+		try
+			LoadPreferences;
+		except
+			ShowDefaultMessageBox ('An error occured while loading the preferences. Some parts of the program may not be configured correctly.', 'Error', mtProgramError);
+		end;
+		DocFile.FileName := WithBackslash (TIGCCFolder) + DocLocation + 'TIGCC.chm';
+		if DirExists (WithBackslash (TIGCCFolder) + ProjectsLocation) then
+			OpenProjectDlg.InitialDir := WithBackslash (TIGCCFolder) + ProjectsLocation
+		else
+			OpenProjectDlg.InitialDir := TIGCCFolder;
+		SaveProjectDlg.InitialDir := OpenProjectDlg.InitialDir;
+		AddFileDlg.InitialDir := OpenProjectDlg.InitialDir;
+		DragAcceptFiles (Handle, True);
+		ParsingUnit.ErrorMessageProc := ErrorMessage;
+		S := '';
+		if ParamCount > 0 then begin
+			if LowerCase (ExtractFileExt (ParamStr (1))) = LowerCase (ProjectFileExt) then
+				ProjectFile := ExpandFileName (ParamStr (1))
+			else
+				S := ExpandFileName (ParamStr (1));
+		end;
+		if Length (ProjectFile) > 0 then begin
+			if Assigned (StartupScreenForm) then
+				StartupScreenForm.DisplayText := 'Opening Project...';
+			FileLoad;
+		end;
+		if Length (S) > 0 then
+			AddSourceFile (S, True);
+		if AutoNews then begin
+			if Assigned (StartupScreenForm) then
+				StartupScreenForm.DisplayText := 'Downloading Headlines...';
+			with TNewsForm.Create (Self) do begin
+				SilentConnect := True;
+				Connect;
+			end;
+		end;
+	except
+		ShowDefaultMessageBox ('An error occured while setting up the application. Some parts of the program may not be configured correctly.', 'Error', mtProgramError);
+	end;
+	StartingAppNow := False;
+
+{$IFDEF CODINGEXT}
+  InitCodingExt;
+{$ENDIF}
+end;
+
+procedure TMainForm.FormDestroy(Sender: TObject);
+var
+	I: Integer;
+begin
+	Closing := True;
+	ClearDebugInfo;
+	ErrorList.Items.Clear;
+	SourceFiles.Free;
+	SyntaxQuillBackup.Free;
+	SyntaxAsmBackup.Free;
+	SyntaxAsmGNUBackup.Free;
+	SyntaxCBackup.Free;
+	if LinkLibHandle <> 0 then
+		FreeLibrary (LinkLibHandle);
+	if TempLockHandle <> INVALID_HANDLE_VALUE then
+		Windows.FindClose (TempLockHandle);
+	try
+		RmDir (Temp);
+	except end;
+	ToolsList.Free;
+	with RecentFiles do begin
+		for I := Count - 1 downto 0 do
+			Objects[I].Free;
+		Free;
+	end;
+end;
+
+procedure TMainForm.AppException(Sender: TObject; E: Exception);
+begin
+	if not (E is ESocketError) then
+		ShowDefaultMessageBox ('Internal Error: Exception ' + E.ClassName + ', Message "' + E.Message + '"'#13#10#13#10'Please fill out a bug report form at http://tigcc.ticalc.org/.', 'Internal Error', mtProgramError);
+end;
+
+procedure TMainForm.ProjectTreeEditing(Sender: TObject; Node: TTreeNode;
+	var AllowEdit: Boolean);
+begin
+	AllowEdit := Assigned (Node.Data) or not Assigned (Node.Parent);
+end;
+
+procedure TMainForm.ProjectAddFiles(Sender: TObject);
+var
+	I: Integer;
+	F: TSourceFile;
+begin
+	if AddFileDlg.Execute then begin
+		for I := AddFileDlg.Files.Count - 1 downto 0 do begin
+			F := AddSourceFile(ExpandFileName(AddFileDlg.Files[I]));
+			if (I = 0) and Assigned (F) and Assigned (F.TreeItem) then
+				SelectNode (F.TreeItem);
+		end;
+		Modify;
+	end else
+		Abort;
+end;
+
+procedure TMainForm.ProjectTreeChange(Sender: TObject; Node: TTreeNode);
+var
+	NewSelection: TTreeNode;
+	NewEditor: TWinControl;
+	IsMemo,
+	DataItem,
+	BinaryType: Boolean;
+begin
+	NewSelection := ProjectTree.Selected;
+	PreviousNode := NewSelection;
+	if not Closing then begin
+		if Assigned (NewSelection) and Assigned (NewSelection.Data) and (TObject (NewSelection.Data) is TSourceFile) then
+			NewEditor := TSourceFile(NewSelection.Data).Editor
+		else
+			NewEditor := NoEditor;
+		if Assigned (EditorToHide) and (EditorToHide <> NewEditor) then
+			EditorToHide.Align := alNone;
+		if NewEditor.Parent <> EditorPanel then
+			NewEditor.Parent := EditorPanel;
+		if NewEditor.Align <> alClient then
+			NewEditor.Align := alClient;
+		IsMemo := NewEditor is TMemoComponent;
+		if IsMemo then begin
+			with TMemoComponent (NewEditor) do begin
+				DrawingSuspended := True;
+				OnEnter := EditorEnter;
+				OnExit := EditorExit;
+				OnKeyDown := EditorKeyDown;
+				OnChange := EditorChange;
+				OnSelectionChange := EditorChange;
+				PopupMenu := EditorPopup;
+			end;
+		end;
+		NewEditor.Show;
+		Update;
+		if IsMemo then
+			with TMemoComponent (NewEditor) do begin
+				DrawingSuspended := False;
+				Repaint;
+			end;
+		if Assigned (EditorToHide) and (EditorToHide <> NewEditor) then
+			EditorToHide.Hide;
+		EditorToHide := nil;
+		DataItem := Assigned (NewSelection) and Assigned (NewSelection.Data);
+		Node := GetSourceTypeFolder (NewSelection);
+		BinaryType := Assigned (Node) and ((Node.Index = TObjectSourceFile.GetClassTreeIndex) or (Node.Index = TArchiveSourceFile.GetClassTreeIndex) or (Node.Index = TOtherSourceFile.GetClassTreeIndex));
+		ActionFileNewFolder.Enabled := Assigned (NewSelection) and Assigned (NewSelection.Parent);
+		ActionTreeItemNewFolder.Enabled := ActionFileNewFolder.Enabled;
+		ActionFileNewFile.Enabled := ActionFileNewFolder.Enabled and (not BinaryType);
+		ActionTreeItemNewFile.Enabled := ActionFileNewFile.Enabled;
+		if ActiveControl = ProjectTree then
+			ActionEditDelete.Enabled := DataItem;
+		ActionFilePrint.Enabled := DataItem and (TObject (NewSelection.Data) is TSourceFile) and TSourceFile(NewSelection.Data).Printable and (Printer.Printers.Count > 0);
+		ActionFilePrintQuickly.Enabled := ActionFilePrint.Enabled;
+		ActionFindFunctions.Enabled := DataItem and (TObject (NewSelection.Data) is TSourceTextSourceFile);
+		UpdateStatusBar;
+	end;
+end;
+
+procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+	if Compiling then
+		CanClose := False
+	else
+		try
+			WarnIfModified;
+			SavePreferences;
+		except
+			CanClose := False;
+		end;
+end;
+
+procedure TMainForm.WarnIfModified;
+var
+	I: Integer;
+begin
+	if Modified then
+		case ShowDefaultMessageBox
+			('The current project has been modified.  Do you want to save the changes?',
+			'Project Modified', mtQuestion, True) of
+			idYes: FileSave;
+			idCancel: Abort;
+		end;
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			with Items [I] as TSourceFile do
+				WarnIfModified;
+end;
+
+procedure TMainForm.FileLoad;
+function StringToRelocFormat(const S: string): TRelocFormat;
+begin
+	if S = 'None' then
+		Result := rfNone
+	else if S = 'Direct' then
+		Result := rfDirect
+	else if S = 'AMS' then
+		Result := rfAMS
+	else if S = 'Kernel' then
+		Result := rfKernel
+	else if S = 'Compressed' then
+		Result := rfCompressed
+	else if S = 'F-Line' then
+		Result := rfFLine
+	else
+		Result := rfUnknown;
+end;
+var
+	F: TOpenFileStatusForm;
+	I,
+	J,
+	Ps: Integer;
+	S,
+	P: string;
+	SL: TStringList;
+	Folder: TFolder;
+	Node,
+	SubNode: TTreeNode;
+	CurrentFile: TSourceFile;
+begin
+	if not Compiling then begin
+		WarnIfModified;
+		Modified := False;
+		OpeningProjectNow := True;
+		Update;
+		F := nil;
+		ProjectTree.Items.BeginUpdate;
+		S := ProjectFile;
+		try
+			FileClear;
+			if (Length (S) > 0) and FileExists (S) then begin
+				if not StartingAppNow then begin
+					try
+						F := TOpenFileStatusForm.Create (Self);
+					except
+						F := nil;
+					end;
+					if Assigned (F) then begin
+						P := ExtractFileName (S);
+						F.FileNameLabel.Caption := 'Opening Project ''' + Copy (P, 1, LastPos ('.', P) - 1) + '''...';
+						F.Show;
+						F.Update;
+					end;
+				end;
+				SHAddToRecentDocs(SHARD_PATH, PChar (S));
+				with TIniFile.Create (S) do try
+					TopNode.Text          := ReadString ('Settings', 'Project Name',                   'Project1');
+					ProjectFile := S;
+					if                       ReadBool   ('Settings', 'Archive',                        False) then
+						ProjectTarget := ptArchive
+					else if                  ReadBool   ('Settings', 'Flash OS',                       False) then
+						ProjectTarget := ptFlashOS
+					else if                  ReadBool   ('Settings', 'Fargo',                          False) then
+						ProjectTarget := ptFargo;
+					UseDataVar            := ReadBool   ('Settings', 'Use Data Variable',              False);
+					DataVar               := ReadString ('Settings', 'Data Variable',                  '');
+					DataVarCopy           := ReadBool   ('Settings', 'Copy Data Variable',             True);
+					DataVarCopyIfArchived := ReadBool   ('Settings', 'Copy Data Variable if Archived', True);
+					Pack                  := ReadBool   ('Settings', 'Pack',                           False);
+					PackVar               := ReadString ('Settings', 'Packed Variable',                '');
+					GCCSwitches           := ReadString ('Settings', 'GCC Switches',                   '');
+					AsSwitches            := ReadString ('Settings', 'GNU Assembler Switches',         '');
+					AsmSwitches           := ReadString ('Settings', 'Assembler Switches',             '');
+					DebugInfo             := ReadBool   ('Settings', 'Debug Info',                     False);
+					StdLib                := ReadBool   ('Settings', 'Standard Library',               True);
+					InitBSS               := ReadBool   ('Settings', 'Initialize BSS',                 True);
+					OptimizeNOPs          := ReadBool   ('Settings', 'Optimize NOPs',                  True);
+					OptimizeReturns       := ReadBool   ('Settings', 'Optimize Returns',               True);
+					OptimizeBranches      := ReadBool   ('Settings', 'Optimize Branches',              True);
+					OptimizeMoves         := ReadBool   ('Settings', 'Optimize Moves',                 True);
+					OptimizeTests         := ReadBool   ('Settings', 'Optimize Tests',                 True);
+					OptimizeCalculations  := ReadBool   ('Settings', 'Optimize Calculations',          True);
+					RemoveUnusedSections  := ReadBool   ('Settings', 'Remove Unused Sections',         True);
+					CutUnusedRanges       := ReadBool   ('Settings', 'Cut Unused Ranges',              True);
+					ReorderSections       := ReadBool   ('Settings', 'Reorder Sections',               True);
+					MergeConstants        := ReadBool   ('Settings', 'Merge Constants',                True);
+					OutputBin             := ReadBool   ('Settings', 'Binary Output',                  False);
+					CommandLine           := ReadString ('Settings', 'Command Line',                   '');
+					PostBuildProcessFile  := ReadString ('Settings', 'Post-Build Process',             '');
+					while Pos ('`', PostBuildProcessFile) > 0 do
+						PostBuildProcessFile [Pos ('`', PostBuildProcessFile)] := '"';
+					if Assigned (PredefinedLibOptions) then
+						with PredefinedLibOptions do begin
+							CalcDests := [];
+							if                                     ReadBool   ('Library Options', 'Use TI-89',                    False) then
+								Include (CalcDests, cdTI89);
+							if                                     ReadBool   ('Library Options', 'Use TI-92 Plus',               False) then
+								Include (CalcDests, cdTI92Plus);
+							if                                     ReadBool   ('Library Options', 'Use V200',                     False) then
+								Include (CalcDests, cdV200);
+							OptimizeCalcConsts                  := ReadBool   ('Library Options', 'Optimize Calc Consts',         False);
+							if                                     ReadBool   ('Library Options', 'Use PreOS',                    False) then
+								KernelFormat := kfCompressedTables
+							else if                                ReadBool   ('Library Options', 'Use Kernel',                   False) then
+								KernelFormat := kfStandard
+							else
+								KernelFormat := kfNone;
+							UseMinAMS                           := ReadBool   ('Library Options', 'Minimum AMS Version Defined',  False);
+							MinAMS                              := ReadString ('Library Options', 'Minimum AMS Version',          '1.00');
+							UnofficialOSSupport                 := ReadBool   ('Library Options', 'Unofficial OS Support',        False);
+							RelocFormat    := StringToRelocFormat (ReadString ('Library Options', 'Reloc Format',                 ''));
+							ROMCallFormat  := StringToRelocFormat (ReadString ('Library Options', 'ROM Call Format',              ''));
+							BSSRefFormat   := StringToRelocFormat (ReadString ('Library Options', 'BSS Ref Format',               ''));
+							DataRefFormat  := StringToRelocFormat (ReadString ('Library Options', 'Data Ref Format',              ''));
+							UseFLineJumps                       := ReadBool   ('Library Options', 'Use F-Line Jumps',             False);
+							Use4ByteFLineJumps                  := ReadBool   ('Library Options', 'Use 4-Byte F-Line Jumps',      False);
+							OptimizeROMCalls                    := ReadBool   ('Library Options', 'Optimize ROM Calls',           False);
+							UseInternalFLineEmulator            := ReadBool   ('Library Options', 'Use Internal F-Line Emulator', False);
+							UseReturnValue                      := ReadBool   ('Library Options', 'Use Return Value',             False);
+							EnableErrorReturn                   := ReadBool   ('Library Options', 'Enable Error Return',          False);
+							SaveScreen                          := ReadBool   ('Library Options', 'Save Screen',                  False);
+						end;
+					SL := TStringList.Create;
+					try
+						ReadSection ('Included Files', SL);
+						for I := 0 to SL.Count - 1 do begin
+							P := SL.Strings [I];
+							S := ReadString ('Included Files', P, '');
+							if Length (S) > 0 then begin
+								if Copy (P, Length (P) - Length (' Folder') + 1, Length (P)) = ' Folder' then begin
+									Delete (P, Length (P) - Length (' Folder') + 1, Length (P));
+									J := SL.IndexOf (P);
+									if J >= 0 then begin
+										Node := TopNode.Item [TSourceFile.GetAppropriateClassFromName (Copy (P, 1, LastPos (' ', P) - 1)).GetClassTreeIndex];
+										repeat
+											Ps := Pos ('\', S);
+											if Ps > 0 then
+												P := Copy (S, 1, Ps - 1)
+											else
+												P := S;
+											SubNode := Node.GetFirstChild;
+											while Assigned (SubNode) and ((not Assigned (SubNode.Data)) or (not (TObject (SubNode.Data) is TFolder)) or (SubNode.Text <> P)) do
+												SubNode := SubNode.GetNextSibling;
+											if Assigned (SubNode) then
+												Node := SubNode
+											else begin
+												Folder := TFolder.Create;
+												Node := ProjectTree.Items.AddChildObject (Node, P, Folder);
+												Folder.TreeItem := Node;
+												with Node do begin
+													ImageIndex    := 0;
+													SelectedIndex := 1;
+												end;
+											end;
+											Delete (S, 1, Length (P) + 1);
+										until Length (S) <= 0;
+										SL.Objects [J] := Node.Data;
+									end;
+								end;
+							end;
+						end;
+						for I := 0 to SL.Count - 1 do begin
+							P := SL.Strings [I];
+							S := ReadString ('Included Files', P, '');
+							if Length (S) > 0 then begin
+								if Copy (P, Length (P) - Length (' Folder') + 1, Length (P)) <> ' Folder' then begin
+									if Pos (':', S) <= 0 then
+										S := ExtractFilePath (ProjectFile) + S;
+									if FileExists (S) then
+										AddSourceFile (S, False, TSourceFile.GetAppropriateClassFromName (Copy (P, 1, LastPos (' ', P) - 1)), TFolder (SL.Objects [I]))
+									else
+										ShowDefaultMessageBox ('File not found:'#13#10#13#10 + S, 'Error', mtProgramError);
+								end;
+							end;
+						end;
+					finally
+						SL.Free;
+					end;
+					S := ReadString ('File Editing', 'Open File', '');
+					if Length (S) > 0 then begin
+						CurrentFile := SourceFiles.FindFile (S);
+						if Assigned (CurrentFile) then
+							CurrentFile.Edit;
+					end;
+				finally
+					Free;
+				end;
+				ProjectTree.FullExpand;
+				NoEditor.Show;
+				UpdateDebugSettings;
+				AddToRecent (ProjectFile);
+			end;
+			SortFiles;
+		finally
+			ProjectTree.Items.EndUpdate;
+			OpeningProjectNow := False;
+			if Assigned (F) then
+				F.Free;
+		end;
+		Modified := False;
+	end;
+end;
+
+procedure TMainForm.FileNew;
+begin
+	if not Compiling then begin
+		WarnIfModified;
+		Modified := False;
+		ProjectFile := '';
+		FileClear;
+	end;
+end;
+
+procedure TMainForm.FileClear;
+procedure TryDeleteNode(Node: TTreeNode);
+var
+	I: Integer;
+begin
+	with Node do begin
+		for I := Count - 1 downto 0 do
+			TryDeleteNode (Item [I]);
+		if Assigned (Data) then
+			Delete;
+	end;
+end;
+begin
+	if not Compiling then begin
+		WarnIfModified;
+		Modified := False;
+		Invalidated := True;
+		ActiveControl := ProjectTree;
+		ErrorList.Items.BeginUpdate;
+		ErrorList.Items.Clear;
+		ErrorList.Items.EndUpdate;
+		ProjectTree.Items.BeginUpdate;
+		ClearDebugInfo;
+		TopNode.Text := 'Project1';
+		SelectNode (TopNode);
+		TryDeleteNode (TopNode);
+		ProjectTree.FullExpand;
+		ProjectTree.Items.EndUpdate;
+		ResetProjectSettings;
+		NoEditor.Show;
+		UpdateDebugSettings;
+		Update;
+		Modified := False;
+	end;
+end;
+
+procedure TMainForm.FileOpen(const FN: string);
+begin
+	if not Compiling then begin
+		WarnIfModified;
+		Modified := False;
+		ProjectTree.Items.BeginUpdate;
+		ProjectFile := FN;
+		FileLoad;
+		ProjectTree.Items.EndUpdate;
+	end;
+end;
+
+procedure TMainForm.FileSave;
+function RelocFormatToString(RelocFormat: TRelocFormat): string;
+begin
+	case RelocFormat of
+		rfNone:        Result := 'None';
+		rfDirect:      Result := 'Direct';
+		rfAMS:         Result := 'AMS';
+		rfKernel:      Result := 'Kernel';
+		rfCompressed:  Result := 'Compressed';
+		rfFLine:       Result := 'F-Line';
+		else           Result := 'Unknown';
+	end;
+end;
+var
+	I,
+	ClassCount: Integer;
+	S: string;
+	SL: TStringList;
+begin
+	if ProjectFile = '' then
+		FileSaveProjectAs (Self)
+	else begin
+		try
+			with SourceFiles do
+				for I := 0 to Count - 1 do
+					with Items [I] as TSourceFile do begin
+						if UpperCase (ExtractFilePath (FileName)) = 'C:\' then
+							FileName := ExtractFilePath (ProjectFile) + LogicalFileName;
+						if Modified or not FileExists (FileName) then
+							Save;
+					end;
+			with TIniFile.Create (ProjectFile) do try
+				WriteBool   ('Settings', 'Archive',                        ProjectTarget = ptArchive);
+				WriteBool   ('Settings', 'Flash OS',                       ProjectTarget = ptFlashOS);
+				WriteBool   ('Settings', 'Fargo',                          ProjectTarget = ptFargo);
+				WriteBool   ('Settings', 'Use Data Variable',              UseDataVar);
+				WriteString ('Settings', 'Data Variable',                  DataVar);
+				WriteBool   ('Settings', 'Copy Data Variable',             DataVarCopy);
+				WriteBool   ('Settings', 'Copy Data Variable if Archived', DataVarCopyIfArchived);
+				WriteBool   ('Settings', 'Pack',                           Pack);
+				WriteString ('Settings', 'Packed Variable',                PackVar);
+				WriteString ('Settings', 'Project Name',                   TopNode.Text);
+				WriteString ('Settings', 'GCC Switches',                   GCCSwitches);
+				WriteString ('Settings', 'GNU Assembler Switches',         AsSwitches);
+				WriteString ('Settings', 'Assembler Switches',             AsmSwitches);
+				WriteBool   ('Settings', 'Debug Info',                     DebugInfo);
+				WriteBool   ('Settings', 'Standard Library',               StdLib);
+				WriteBool   ('Settings', 'Initialize BSS',                 InitBSS);
+				WriteBool   ('Settings', 'Optimize NOPs',                  OptimizeNOPs);
+				WriteBool   ('Settings', 'Optimize Returns',               OptimizeReturns);
+				WriteBool   ('Settings', 'Optimize Branches',              OptimizeBranches);
+				WriteBool   ('Settings', 'Optimize Moves',                 OptimizeMoves);
+				WriteBool   ('Settings', 'Optimize Tests',                 OptimizeTests);
+				WriteBool   ('Settings', 'Optimize Calculations',          OptimizeCalculations);
+				WriteBool   ('Settings', 'Remove Unused Sections',         RemoveUnusedSections);
+				WriteBool   ('Settings', 'Cut Unused Ranges',              CutUnusedRanges);
+				WriteBool   ('Settings', 'Reorder Sections',               ReorderSections);
+				WriteBool   ('Settings', 'Merge Constants',                MergeConstants);
+				WriteBool   ('Settings', 'Binary Output',                  OutputBin);
+				WriteString ('Settings', 'Command Line',                   CommandLine);
+				S := PostBuildProcessFile;
+				while Pos ('"', S) > 0 do
+					S [Pos ('"', S)] := '`';
+				WriteString ('Settings', 'Post-Build Process',             S);
+				if Assigned (PredefinedLibOptions) then
+					with PredefinedLibOptions do begin
+						WriteBool   ('Library Options', 'Use TI-89',                    cdTI89     in CalcDests);
+						WriteBool   ('Library Options', 'Use TI-92 Plus',               cdTI92Plus in CalcDests);
+						WriteBool   ('Library Options', 'Use V200',                     cdV200     in CalcDests);
+						WriteBool   ('Library Options', 'Optimize Calc Consts',         OptimizeCalcConsts);
+						WriteBool   ('Library Options', 'Use Kernel',                   KernelFormat <> kfNone);
+						WriteBool   ('Library Options', 'Use PreOS',                    KernelFormat = kfCompressedTables);
+						WriteBool   ('Library Options', 'Minimum AMS Version Defined',  UseMinAMS);
+						WriteString ('Library Options', 'Minimum AMS Version',          MinAMS);
+						WriteBool   ('Library Options', 'Unofficial OS Support',        UnofficialOSSupport);
+						WriteString ('Library Options', 'Reloc Format',                 RelocFormatToString (RelocFormat));
+						WriteString ('Library Options', 'ROM Call Format',              RelocFormatToString (ROMCallFormat));
+						WriteString ('Library Options', 'BSS Ref Format',               RelocFormatToString (BSSRefFormat));
+						WriteString ('Library Options', 'Data Ref Format',              RelocFormatToString (DataRefFormat));
+						WriteBool   ('Library Options', 'Use F-Line Jumps',             UseFLineJumps);
+						WriteBool   ('Library Options', 'Use 4-Byte F-Line Jumps',      Use4ByteFLineJumps);
+						WriteBool   ('Library Options', 'Optimize ROM Calls',           OptimizeROMCalls);
+						WriteBool   ('Library Options', 'Use Internal F-Line Emulator', UseInternalFLineEmulator);
+						WriteBool   ('Library Options', 'Use Return Value',             UseReturnValue);
+						WriteBool   ('Library Options', 'Enable Error Return',          EnableErrorReturn);
+						WriteBool   ('Library Options', 'Save Screen',                  SaveScreen);
+					end;
+				EraseSection ('Included Files');
+				SL := TStringList.Create;
+				try
+					with SourceFiles do
+						for I := 0 to Count - 1 do
+							with Items [I] as TSourceFile do
+								if InProject then begin
+									S := SL.Values [ClassItemName];
+									if Length (S) > 0 then
+										ClassCount := StrToInt (S) + 1
+									else
+										ClassCount := 1;
+									SL.Values [ClassItemName] := IntToStr (ClassCount);
+									WriteString ('Included Files', ClassItemName + ' ' + IntToStr (ClassCount), DynamicName);
+									S := FolderPath;
+									if Length (S) > 0 then
+										WriteString ('Included Files', ClassItemName + ' ' + IntToStr (ClassCount) + ' Folder', S);
+								end;
+				finally
+					SL.Free;
+				end;
+				S := '';
+				if Assigned (ProjectTree.Selected) and Assigned (ProjectTree.Selected.Data) and (TObject (ProjectTree.Selected.Data) is TSourceFile) then
+					S := TSourceFile(ProjectTree.Selected.Data).FileName;
+				WriteString ('File Editing', 'Open File', S);
+				UpdateFile;
+			finally
+				Free;
+			end;
+			Modified := False;
+		except
+			ShowDefaultMessageBox ('Error saving project file.', 'Error', mtProgramError);
+		end;
+		AddToRecent (ProjectFile);
+	end;
+end;
+
+procedure TMainForm.FileSaveAs(const FN: string);
+var
+	I: Integer;
+begin
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			with Items [I] as TSourceFile do
+				if Pos ('\', DynamicName) <= 0 then
+					WriteToFile (ExtractFilePath (FN) + DynamicName, True);
+	ProjectFile := FN;
+	FileSave;
+end;
+
+procedure TMainForm.ProjectTreeDeletion(Sender: TObject; Node: TTreeNode);
+begin
+	PreviousNode := nil;
+	EditorToHide := nil;
+	if Assigned (Node.Data) then
+		if TObject (Node.Data) is TSourceFile then begin
+			with TSourceFile (Node.Data) do begin
+				TreeItem := nil;
+				Free;
+			end;
+		end else
+			with TObject (Node.Data) do
+				Free;
+	ProjectTree.Invalidate;
+end;
+
+procedure TMainForm.FileExit(Sender: TObject);
+begin
+	Close;
+end;
+
+procedure TMainForm.FileNewProject(Sender: TObject);
+begin
+	WarnIfModified;
+	Modified := False;
+	FileNew;
+end;
+
+procedure TMainForm.TreeItemRemove(Sender: TObject);
+var
+	Node,
+	CurNode: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if (not Compiling) and Assigned (Node) and Assigned (Node.Data) then begin
+		CurNode := Node;
+		while Assigned (CurNode) and (CurNode <> Node.GetNextSibling) do begin
+			if Assigned (CurNode.Data) and (TObject (CurNode.Data) is TSourceFile) then
+				TSourceFile(CurNode.Data).WarnIfModified;
+			CurNode := CurNode.GetNext;
+			if Node.GetNextSibling = nil then
+				break;
+		end;
+		Node.Delete;
+		Modify;
+	end;
+end;
+
+procedure TMainForm.TreeItemDelete(Sender: TObject);
+var
+	Node: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if (not Compiling) and Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then begin
+		if ShowDefaultMessageBox
+			('Are you sure you want to delete this source file?  You cannot undo this operation.',
+			'Confirm Deletion', mtQuestion) = idYes then begin
+			with TSourceFile (Node.Data) do
+				if (FileName <> '') and FileExists (FileName) then
+					DeleteFile (FileName);
+			Node.Delete;
+			Modify;
+		end;
+	end;
+end;
+
+procedure TMainForm.CopyHeaders;
+var
+	I,
+	J: Integer;
+	HasA68kFiles: Boolean;
+begin
+	HasA68kFiles := False;
+	with SourceFiles do begin
+		for I := 0 to Count - 1 do
+			if Items [I] is TAsmSourceFile then begin
+				HasA68kFiles := True;
+				Break;
+			end;
+		if HasA68kFiles then
+			with TFileReferences.Create do try
+				SearchForFiles (WithBackslash (TIGCCFolder) + ASMIncludeLocation + '*.*', atAll);
+				for J := 0 to Count - 1 do
+					CopyFile (PChar (Items[J].FullName), PChar (Temp + ExtractFileName (Items[J].FullName)), False);
+			finally
+				Free;
+			end;
+		for I := 0 to Count - 1 do begin
+			if Items [I] is THeaderSourceFile then begin
+				with Items [I] as THeaderSourceFile do begin
+					if Invalidated then
+						RecompileFiles;
+					if InProject then
+						SplitAndWriteToFile (Temp + LogicalFileName);
+				end;
+			end else if Items [I] is TOtherSourceFile then
+				with Items [I] as TSourceFile do
+					if InProject then
+						WriteToFile (Temp + LogicalFileName);
+		end;
+	end;
+end;
+
+procedure TMainForm.DeleteHeaders;
+var
+	I: Integer;
+	FN: string;
+begin
+	with TFileReferences.Create do try
+		SearchForFiles (Temp + '*.h', atAll);
+		for I := 0 to Count - 1 do try
+			DeleteFile (Items[I].FullName);
+		except end;
+	finally
+		Free;
+	end;
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			if (Items [I] is THeaderSourceFile) or (Items [I] is TOtherSourceFile) then
+				with Items [I] as TSourceFile do begin
+					FN := Temp + LogicalFileName;
+					if FileExists (FN) then try
+						DeleteFile (FN);
+					except end;
+					RemovePathFor (FN, Temp);
+				end;
+end;
+
+procedure TMainForm.TreeItemCompile(Sender: TObject);
+var
+	Node: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if (not Compiling) and Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) and (TSourceFile(Node.Data).Compilable) then begin
+		BeginCompilation;
+		CopyHeaders;
+		TSourceFile(Node.Data).Compile;
+		DeleteHeaders;
+		EndCompilation;
+	end;
+end;
+
+procedure TMainForm.CloseErrorsButtonClick(Sender: TObject);
+begin
+	HideErrors;
+end;
+
+procedure TMainForm.AddError(const Line: string; BugTp: TBugType; SourceF: string; ErrFunc: string; ErrMessage: string; SourceLn: Integer; Offset: Integer);
+var
+	I,
+	J: Integer;
+	O: TFoundError;
+	Ignore: Boolean;
+	Token: string;
+begin
+	ErrMessage := Trim (ErrMessage);
+	if ErrMessage <> '' then begin
+		Ignore := False;
+		if BugTp in [btWarning, btInfo] then begin
+			if ((ErrFunc = '') and (UpperCase (ErrMessage) = '''STATIC'' IS NOT AT BEGINNING OF DECLARATION'))
+				or (Pos ('__DUMMY__', UpperCase (ErrMessage)) > 0)
+				or (Pos ('''__R''', UpperCase (ErrMessage)) > 0)
+				or (Pos ('MULTI-LINE STRING LITERALS ARE DEPRECATED', UpperCase (ErrMessage)) > 0) then
+				Ignore := True;
+		end else begin
+			if (Pos ('(EACH UNDECLARED IDENTIFIER IS REPORTED ONLY ONCE', UpperCase (ErrMessage)) > 0)
+				or (Pos ('FOR EACH FUNCTION IT APPEARS IN.)', UpperCase (ErrMessage)) > 0) then
+				Ignore := True;
+		end;
+		if not Ignore then begin
+			if ErrFunc = '__main' then
+				ErrFunc := '_main';
+			if ErrFunc = '__exit' then
+				ErrFunc := '_exit';
+			ErrorList.Items.BeginUpdate;
+			try
+				ErrMessage [1] := UpCase (ErrMessage [1]);
+				O := TFoundError.Create;
+				with O do begin
+					SourceFile := nil;
+					if (Length (SourceF) > 0) and (LowerCase (ExtractFileExt (SourceF)) <> '.exe') and (LowerCase (ExtractFileExt (SourceF)) <> '.a') then try
+						if Pos ('\', SourceF) > 0 then begin
+							SourceFile := SourceFiles.FindFile (SourceF);
+							if (not Assigned (SourceFile)) and (LowerCase (ExtractFileExt (SourceF)) = '.o') then begin
+								SourceFile := SourceFiles.FindFile (ChangeFileExt (SourceF, '.c'));
+								if not Assigned (SourceFile) then
+									SourceFile := SourceFiles.FindFile (ChangeFileExt (SourceF, '.s'));
+								if not Assigned (SourceFile) then
+									SourceFile := SourceFiles.FindFile (ChangeFileExt (SourceF, '.asm'));
+							end;
+						end else begin
+							SourceFile := SourceFiles.FindFileNameOnly (SourceF);
+							if (not Assigned (SourceFile)) and (LowerCase (ExtractFileExt (SourceF)) = '.o') then begin
+								SourceFile := SourceFiles.FindFileNameOnly (ChangeFileExt (SourceF, '.c'));
+								if not Assigned (SourceFile) then
+									SourceFile := SourceFiles.FindFileNameOnly (ChangeFileExt (SourceF, '.s'));
+								if not Assigned (SourceFile) then
+									SourceFile := SourceFiles.FindFileNameOnly (ChangeFileExt (SourceF, '.asm'));
+							end;
+						end;
+						if not Assigned (SourceFile) then begin
+							if (Pos ('\', SourceF) > 0) and FileExists (SourceF) then
+								SourceFile := AddSourceFile (SourceF, True)
+							else if FileExists (WithBackslash (TIGCCFolder) + CIncludeLocation + ExtractFileName (SourceF)) then
+								SourceFile := AddSourceFile (WithBackslash (TIGCCFolder) + CIncludeLocation + ExtractFileName (SourceF), True)
+							else if FileExists (WithBackslash (TIGCCFolder) + AsmIncludeLocation + ExtractFileName (SourceF)) then
+								SourceFile := AddSourceFile (WithBackslash (TIGCCFolder) + AsmIncludeLocation + ExtractFileName (SourceF), True);
+						end;
+					except end;
+					BugType := BugTp;
+					WholeLine := Line;
+					ErrorMessage := ErrMessage;
+					ErrFunction := ErrFunc;
+					if Assigned (SourceFile) and (SourceFile is TTextSourceFile) then
+						with SourceFile as TTextSourceFile do
+							if Assigned (TextEditor) then begin
+								I := GetCompiledLineStart (SourceLn) + Offset;
+								if I > 0 then begin
+									if Pos ('''', ErrorMessage) > 0 then begin
+										Token := Copy (ErrorMessage, Pos ('''', ErrorMessage) + 1, Length (ErrorMessage));
+										Delete (Token, Pos ('''', Token), Length (Token));
+										if Length (Token) > 0 then begin
+											J := I;
+											while (J <= TextEditor.TextLength) and (TextEditor.Text [J] in [#9, #10, #13, #32]) and (Copy (TextEditor.Text, J, Length (Token)) <> Token) do
+												Inc (J);
+											if Copy (TextEditor.Text, J, Length (Token)) = Token then
+												I := J;
+										end;
+									end;
+									O.Range := TMCRange.Create (TextEditor.TrackedRanges);
+									O.Range.RStart := I;
+									O.Range.OnOverwrite := DeleteError;
+								end else
+									O.Range := nil;
+							end;
+				end;
+				with ErrorList.Items.Add do begin
+					Data := Pointer (O);
+					ImageIndex := Integer (BugTp);
+					Caption := ErrMessage;
+					if Assigned (O.SourceFile) then
+						SubItems.Add (O.SourceFile.SourceName)
+					else
+						SubItems.Add ('');
+					SubItems.Add (ErrFunc);
+					ShowErrors;
+					if JumpToError and (BugTp = btError) and (not Assigned (ErrorList.Selected)) then begin
+						Selected := True;
+						ErrorListClick (Self);
+					end;
+				end;
+			except end;
+			ErrorList.Items.EndUpdate;
+		end;
+	end;
+	UpdateErrorWindow;
+end;
+
+procedure TMainForm.ClearErrors;
+begin
+	HideErrors;
+	with ErrorList.Items do begin
+		BeginUpdate;
+		Clear;
+		EndUpdate;
+	end;
+	ActionProjectShowErrors.Enabled := False;
+end;
+
+procedure TMainForm.HideErrors;
+begin
+	Splitter2.Hide;
+	ErrWinPanel.Hide;
+	ActionProjectShowErrors.Checked := False;
+end;
+
+procedure TMainForm.ShowErrors;
+begin
+	if ErrorList.Items.Count > 0 then begin
+		ErrWinPanel.Show;
+		Splitter2.Show;
+		Splitter2.Top := ErrWinPanel.Top - Splitter2.Height;
+		ActionProjectShowErrors.Checked := True;
+		ErrorList.Refresh;
+	end;
+end;
+
+procedure TMainForm.ErrorListDeletion(Sender: TObject; Item: TListItem);
+var
+	O: TObject;
+begin
+	if Assigned (Item.Data) then begin
+		O := TObject(Item.Data);
+		Item.Data := nil;
+		O.Free;
+	end;
+end;
+
+procedure TMainForm.UpdateErrorWindow;
+var
+	I: Integer;
+	EC,
+	WC: Integer;
+begin
+	with ErrorList, Items do begin
+		EC := 0;
+		WC := 0;
+		for I := 0 to Count - 1 do
+			with TFoundError (Item[I].Data) do
+				case BugType of
+					btWarning:
+						Inc (WC);
+					btError:
+						Inc (EC);
+				end;
+		ErrorsLabel.Caption := IntToStr (EC);
+		WarningsLabel.Caption := IntToStr (WC);
+		if Count <= 0 then
+			HideErrors;
+	end;
+	ActionProjectShowErrors.Enabled := ErrorList.Items.Count > 0;
+	if not ActionProjectShowErrors.Enabled then
+		ActionProjectShowErrors.Checked := False;
+end;
+
+procedure TMainForm.TreeItemSave(Sender: TObject);
+var
+	Node: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then
+		TSourceFile(Node.Data).Save;
+end;
+
+procedure TMainForm.HelpDocumentation(Sender: TObject);
+begin
+	try
+		DocFile.Display;
+	except
+		ShowDefaultMessageBox ('Error opening documentation.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.EditorEnter(Sender: TObject);
+begin
+	ActionEditPaste.Enabled := True;
+	ActionEditSelectAll.Enabled := True;
+	ActionEditIncreaseIndent.Enabled := True;
+	ActionEditDecreaseIndent.Enabled := True;
+	ActionFindOpenFile.Enabled := True;
+	UpdateEditButtons;
+end;
+
+procedure TMainForm.EditorExit(Sender: TObject);
+begin
+	ActionEditDelete.Enabled := False;
+	ActionEditCut.Enabled := False;
+	ActionEditCopy.Enabled := False;
+	ActionEditPaste.Enabled := False;
+	ActionEditSelectAll.Enabled := False;
+	ActionEditIncreaseIndent.Enabled := False;
+	ActionEditDecreaseIndent.Enabled := False;
+	ActionFindOpenFile.Enabled := False;
+	ActionEditUndo.Enabled := False;
+	ActionEditRedo.Enabled := False;
+end;
+
+procedure TMainForm.EditUndo(Sender: TObject);
+begin
+	if Assigned (CurrentEditor) then
+		CurrentEditor.Undo;
+end;
+
+procedure TMainForm.EditRedo(Sender: TObject);
+begin
+	if Assigned (CurrentEditor) then
+		CurrentEditor.Redo;
+end;
+
+procedure TMainForm.EditClear(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) and (ActiveControl = Editor) then
+		Editor.ClearSelection
+	else if ActiveControl = ProjectTree then
+		TreeItemRemove (Sender);
+end;
+
+procedure TMainForm.EditCut(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) and (ActiveControl = Editor) then
+		Editor.CutToClipboard;
+end;
+
+procedure TMainForm.EditCopy(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) and (ActiveControl = Editor) then
+		Editor.CopyToClipboard;
+end;
+
+procedure TMainForm.EditPaste(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) and (ActiveControl = Editor) then
+		Editor.PasteFromClipboard;
+end;
+
+procedure TMainForm.EditSelectAll(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) and (ActiveControl = Editor) then
+		Editor.SelectAll;
+end;
+
+procedure TMainForm.ProjectCompile(Sender: TObject);
+var
+	I: Integer;
+begin
+	if not Compiling then begin
+		if AutoSave then
+			FileSave
+		else
+			with SourceFiles do
+				for I := 0 to Count - 1 do
+					with Items [I] as TSourceFile do
+						if not InProject then
+							Save;
+		BeginCompilation;
+		CompileProject;
+		EndCompilation;
+	end;
+end;
+
+procedure TMainForm.ProjectMake(Sender: TObject);
+begin
+	MakeFileWrapped;
+	DisplayFolderMessage;
+end;
+
+procedure TMainForm.MakeFileWrapped;
+var
+	I: Integer;
+begin
+	if not Compiling then begin
+		if AutoSave then
+			FileSave
+		else
+			with SourceFiles do
+				for I := 0 to Count - 1 do
+					with Items [I] as TSourceFile do
+						if not InProject then
+							Save;
+		OperationSuccessful := False;
+		if ProjectFile = '' then
+			ShowDefaultMessageBox ('You need to save your project before you can create executable files.', 'Project not Saved', mtProgramError)
+		else begin
+			BeginCompilation;
+			CompileProject;
+			Application.ProcessMessages;
+			if OperationSuccessful and not OperationCancelled then
+				MakeFile;
+			EndCompilation;
+		end;
+	end;
+end;
+
+procedure TMainForm.MakeFile;
+	procedure FileNotCompiled(const FileName: string);
+	begin
+		ShowDefaultMessageBox
+			('The file ''' + FileName + ''' has not been compiled.  You have to compile it first before you can link it to your project.',
+			'No Object File', mtProgramError);
+	end;
+var MainFiles: array [TCalcDest] of string;
+	procedure HandleContents(const ProjectFile, FolderName, VarName, DataFolderName, DataVarName: string; Pack: Boolean; const PackVar: string; CalcDest: TCalcDest);
+	var
+		InputStream,
+		OutputStream: TMemoryStream;
+		OutputSize: LongWord;
+		FileSize: Integer;
+		F: file;
+		B: Byte;
+	begin
+		CompUpdate;
+		OperationSuccessful := False;
+		with LinkOutputFiles [CalcDest, frMain] do
+			if Assigned (Data) then begin
+				OutputStream := TMemoryStream.Create;
+				try
+					if OSUpgrade then begin
+						OutputSize := GetOSUpgradeFileSize (Data.Size, OutputBin);
+						OutputStream.Size := OutputSize;
+						ProduceOSUpgradeFile (OutputStream.Memory, Data.Memory, Data.Size, OutputBin);
+						MainFiles [CalcDest] := ChangeFileExt (ProjectFile, GetOSUpgradeFileExt (CalcDest, OutputBin));
+						OutputStream.SaveToFile (MainFiles [CalcDest]);
+						if LongWord (ProgSize) < OutputSize then
+							ProgSize := OutputSize;
+						OperationSuccessful := True;
+					end else begin
+						FileSize := 2 + Data.Size + 1;
+						if Pack then begin
+							AssignFile (F, Temp + 'tempprog.bin');
+							Rewrite (F, 1);
+							B := (FileSize - 2) shr 8;
+							BlockWrite (F, B, 1);
+							B := (FileSize - 2);
+							BlockWrite (F, B, 1);
+							BlockWrite (F, Data.Memory^, Data.Size);
+							B := Tag;
+							BlockWrite (F, B, 1);
+							CloseFile (F);
+							MainConsole.Title := 'Compressor';
+							CompUpdate;
+							try
+								MainConsole.StartProcess (WithBackslash (TIGCCFolder) + PackLocation + 'Pack.exe', 'tempprog.bin tempprog.pck', WithoutBackslash (Temp));
+								WaitForMainConsole ('Compression');
+							except
+								ShowDefaultMessageBox ('Could not start compressor.', 'Error', mtProgramError);
+							end;
+							CompUpdate;
+							if not OperationCancelled then begin
+								if FileExists (Temp + 'tempprog.pck') then begin
+									InputStream := TMemoryStream.Create;
+									with InputStream do try
+										LoadFromFile (Temp + 'tempprog.pck');
+										OutputSize := GetTransferFileSize (Size, 'ppg', OutputBin);
+										if OutputSize > 0 then begin
+											OutputStream.Size := OutputSize;
+											ProduceTransferFile (OutputStream.Memory, Memory, Size, CalcDest, FolderName, PackVar, $F8, 'ppg', OutputBin);
+											MainFiles [CalcDest] := ChangeFileExt (ProjectFile, GetTransferFileExt (CalcDest, $F8, OutputBin));
+											OutputStream.SaveToFile (MainFiles [CalcDest]);
+											if LongWord (ProgSize) < OutputSize then
+												ProgSize := OutputSize;
+											OperationSuccessful := True;
+										end else
+											ShowDefaultMessageBox ('Compressed size of ' + IntToStr (Size) + ' bytes is too large, unexpectedly.', 'Error', mtProgramError);
+									finally
+										Free;
+									end;
+								end else
+									ShowDefaultMessageBox ('Compression failed. Please check the program size.', 'Error', mtProgramError);
+							end;
+							if FileExists (Temp + 'tempprog.bin') then
+								DeleteFile (Temp + 'tempprog.bin');
+							if FileExists (Temp + 'tempprog.pck') then
+								DeleteFile (Temp + 'tempprog.pck');
+						end else begin
+							OutputSize := GetTransferFileSize (Data.Size, VarExt, OutputBin);
+							if OutputSize > 0 then begin
+								OutputStream.Size := OutputSize;
+								ProduceTransferFile (OutputStream.Memory, Data.Memory, Data.Size, CalcDest, FolderName, VarName, Tag, VarExt, OutputBin);
+								MainFiles [CalcDest] := ChangeFileExt (ProjectFile, GetTransferFileExt (CalcDest, Tag, OutputBin));
+								OutputStream.SaveToFile (MainFiles [CalcDest]);
+								if LongWord (ProgSize) < OutputSize then
+									ProgSize := OutputSize;
+								OperationSuccessful := True;
+							end else
+								ShowDefaultMessageBox ('Variable size of ' + IntToStr (FileSize) + ' bytes is too large, unexpectedly.', 'Error', mtProgramError);
+						end;
+					end;
+				finally
+					OutputStream.Free;
+				end;
+				CompUpdate;
+			end else
+				ShowDefaultMessageBox ('Unexpected destination calculator mismatch.', 'Error', mtProgramError);
+		with LinkOutputFiles [CalcDest, frData] do
+			if Assigned (Data) and (not OSUpgrade) then begin
+				FileSize := 2 + Data.Size + 1;
+				OutputStream := TMemoryStream.Create;
+				try
+					OutputSize := GetTransferFileSize (Data.Size, VarExt, OutputBin);
+					if OutputSize > 0 then begin
+						OutputStream.Size := OutputSize;
+						ProduceTransferFile (OutputStream.Memory, Data.Memory, Data.Size, CalcDest, DataFolderName, DataVarName, Tag, VarExt, OutputBin);
+						OutputStream.SaveToFile (ChangeFileExt (ChangeFileExt (ProjectFile, '') + '-data', GetTransferFileExt (CalcDest, Tag, OutputBin)));
+						OperationSuccessful := True;
+					end else
+						ShowDefaultMessageBox ('Data variable size of ' + IntToStr (FileSize) + ' bytes is too large, unexpectedly.', 'Error', mtProgramError);
+				finally
+					OutputStream.Free;
+				end;
+				CompUpdate;
+			end;
+	end;
+	procedure CreatePackStarter(const ProjectFile, StarterFileName, FolderName, VarName, PackVar: string; CalcDests: TCalcDests);
+	var
+		CurCalcDest: TCalcDest;
+		CustomStarterObject: string;
+		ObjectFileNames: array [0..1] of PChar;
+		DataVarInfo: TLinkLibDataVarInfo;
+		OptimizeInfo: TLinkLibOptimizeInfo;
+	begin
+		CompUpdate;
+		OperationSuccessful := False;
+		for CurCalcDest := FirstCalcDest to LastCalcDest do begin
+			LinkOutputFiles[CurCalcDest,frMain].Data := nil;
+			LinkOutputFiles[CurCalcDest,frData].Data := nil;
+		end;
+		try
+			CustomStarterObject := Temp + StarterFileName;
+			if FileExists (WithBackslash (TIGCCFolder) + PStarterLocation + StarterFileName) then try
+				ParsePStarter (WithBackslash (TIGCCFolder) + PStarterLocation + StarterFileName, CustomStarterObject, PackVar);
+			except
+				ShowDefaultMessageBox ('Error processing starter object file.', 'Error', mtProgramError);
+				Exit;
+			end else begin
+				ShowDefaultMessageBox ('Cannot find starter object file.', 'Error', mtProgramError);
+				Exit;
+			end;
+			if not OperationCancelled then begin
+				ObjectFileNames [0] := PChar (CustomStarterObject);
+				ObjectFileNames [1] := nil;
+				FillChar (DataVarInfo, SizeOf (DataVarInfo), 0);
+				FillChar (OptimizeInfo, SizeOf (OptimizeInfo), 0);
+				if Assigned (LinkLibLinkFiles) then
+					OperationSuccessful := LinkLibLinkFiles (@ObjectFileNames, nil, LinkLibError, LinkLibGetOutputFile, nil, False, False, False, DataVarInfo, OptimizeInfo, False) = 0
+				else
+					ShowDefaultMessageBox ('Linker not loaded.', 'Error', mtProgramError);
+			end;
+			for CurCalcDest := cdTI89 to cdV200 do
+				if OperationSuccessful and (not OperationCancelled) and (CurCalcDest in CalcDests) then
+					HandleContents (ProjectFile, FolderName, VarName, '', '', False, '', CurCalcDest);
+		finally
+			for CurCalcDest := FirstCalcDest to LastCalcDest do begin
+				if Assigned (LinkOutputFiles[CurCalcDest,frMain].Data) then
+					LinkOutputFiles[CurCalcDest,frMain].Data.Free;
+				if Assigned (LinkOutputFiles[CurCalcDest,frData].Data) then
+					LinkOutputFiles[CurCalcDest,frData].Data.Free;
+				LinkOutputFiles[CurCalcDest,frMain].Data := nil;
+				LinkOutputFiles[CurCalcDest,frData].Data := nil;
+			end;
+			if FileExists (CustomStarterObject) then
+				DeleteFile (CustomStarterObject);
+		end;
+	end;
+var
+	FolderName,
+	VarName,
+	DataFolderName,
+	DataVarName: array [0..MaxNameLength] of Char;
+	I,
+	P: Integer;
+	S1,
+	DestFile: string;
+	Node: TTreeNode;
+	SourceFile: TSourceFile;
+	FileNameList: TStringList;
+	ObjectFileNames,
+	ArchiveFileNames: PPChar;
+	ObjectFileCount,
+	ArchiveFileCount: Integer;
+	DataVarInfo: TLinkLibDataVarInfo;
+	CalcDests: TCalcDests;
+	CurCalcDest: TCalcDest;
+	SR: TSearchRec;
+begin
+	UpdateErrorWindow;
+	OperationCancelled := False;
+	OperationSuccessful := False;
+	ProgSize := 0;
+	CalcDests := [];
+	OperationSuccessful := True;
+	with TopNode do begin
+		I := Pos ('\', Text);
+		if I > 0 then begin
+			StrPLCopy (VarName, LowerCase (Copy (Text, I + 1, MaxNameLength)), MaxNameLength);
+			StrPLCopy (FolderName, LowerCase (Copy (Text, 1, I - 1)), MaxNameLength);
+			CharLower (FolderName);
+		end else begin
+			StrPLCopy (VarName, LowerCase (Text), MaxNameLength);
+			FolderName := 'main';
+		end;
+		CharLower (VarName);
+	end;
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			with TSourceFile (Items [I]) do
+				if InProject and Compilable and (not FileExists (ChangeFileExt (FileName, '.o'))) then begin
+					OperationSuccessful := False;
+					FileNotCompiled (SourceName);
+				end;
+	I := Pos ('\', DataVar);
+	if I > 0 then begin
+		StrPLCopy (DataVarName, LowerCase (Copy (DataVar, I + 1, MaxNameLength)), MaxNameLength);
+		StrPLCopy (DataFolderName, LowerCase (Copy (DataVar, 1, I - 1)), MaxNameLength);
+		CharLower (DataFolderName);
+	end else begin
+		StrPLCopy (DataVarName, LowerCase (DataVar), MaxNameLength);
+		DataFolderName := FolderName;
+	end;
+	CharLower (DataVarName);
+	if OperationSuccessful then begin
+		OperationSuccessful := False;
+		if Assigned (LinkLibLinkFiles) and Assigned (LinkLibCreateArchive) then begin
+			CompStartFile;
+			CompSetMessage ('Linking Project ''' + WithoutExt (ExtractFileName (ProjectFile)) + '''');
+			if FileExists (ChangeFileExt (ProjectFile, '-titanium.89z')) then
+				DeleteFile (ChangeFileExt (ProjectFile, '-titanium.89z'));
+			ObjectFileCount := 0;
+			ObjectFileNames := nil;
+			ArchiveFileCount := 0;
+			ArchiveFileNames := nil;
+			FileNameList := TStringList.Create;
+			try
+				Node := TopNode;
+				while Assigned (Node) do begin
+					if Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then begin
+						SourceFile := Node.Data;
+						if Assigned (SourceFile) then
+							with SourceFile do
+								if InProject then begin
+									if SourceFile is TArchiveSourceFile then begin
+										Inc (ArchiveFileCount);
+										ReallocMem (ArchiveFileNames, SizeOf (PChar) * (ArchiveFileCount + 1));
+										ArchiveFileNames [ArchiveFileCount - 1] := PChar (FileNameList.Strings [FileNameList.Add (FileName)]);
+										ArchiveFileNames [ArchiveFileCount - 0] := nil;
+									end else if Compilable or (SourceFile is TObjectSourceFile) then begin
+										Inc (ObjectFileCount);
+										ReallocMem (ObjectFileNames, SizeOf (PChar) * (ObjectFileCount + 1));
+										ObjectFileNames [ObjectFileCount - 1] := PChar (FileNameList.Strings [FileNameList.Add (ChangeFileExt (FileName, '.o'))]);
+										ObjectFileNames [ObjectFileCount] := nil;
+									end;
+								end;
+					end;
+					Node := Node.GetNext;
+				end;
+				if StdLib then begin
+					if ProjectTarget = ptFlashOS then
+						S1 := WithBackslash (TIGCCFolder) + StdLibLocation + 'flashos.a'
+					else if ProjectTarget = ptFargo then
+						S1 := WithBackslash (TIGCCFolder) + StdLibLocation + 'fargo.a'
+					else
+						S1 := WithBackslash (TIGCCFolder) + StdLibLocation + 'tigcc.a';
+					if FileExists (S1) then begin
+						Inc (ArchiveFileCount);
+						ReallocMem (ArchiveFileNames, SizeOf (PChar) * (ArchiveFileCount + 1));
+						ArchiveFileNames [ArchiveFileCount - 1] := PChar (FileNameList.Strings [FileNameList.Add (S1)]);
+						ArchiveFileNames [ArchiveFileCount] := nil;
+					end;
+				end;
+				if ProjectTarget = ptArchive then begin
+					DestFile := ChangeFileExt (ProjectFile, '.a');
+					OperationSuccessful := LinkLibCreateArchive (PChar (DestFile), ObjectFileNames, LinkLibError, True) = 0;
+					if OperationSuccessful then begin
+						if FindFirst (DestFile, faAnyFile, SR) = 0 then
+							ProgSize := SR.Size;
+						FindClose (SR);
+					end;
+				end else begin
+					for CurCalcDest := FirstCalcDest to LastCalcDest do begin
+						LinkOutputFiles[CurCalcDest,frMain].Data := nil;
+						LinkOutputFiles[CurCalcDest,frData].Data := nil;
+					end;
+					try
+						FillChar (DataVarInfo, SizeOf (DataVarInfo), 0);
+						FillChar (OptimizeInfo, SizeOf (OptimizeInfo), 0);
+						if UseDataVar then
+							with DataVarInfo do begin
+								VarName := PChar (LowerCase (MasterUnit.DataVar));
+								CreateCopy := MasterUnit.DataVarCopy;
+								CopyOnlyIfArchived := MasterUnit.DataVarCopyIfArchived;
+							end;
+						with OptimizeInfo do begin
+							RemoveUnused     := MasterUnit.RemoveUnusedSections;
+							OptimizeNOPs     := MasterUnit.OptimizeNOPs;
+							OptimizeReturns  := MasterUnit.OptimizeReturns;
+							OptimizeBranches := MasterUnit.OptimizeBranches;
+							OptimizeMoves    := MasterUnit.OptimizeMoves;
+							OptimizeTests    := MasterUnit.OptimizeTests;
+							OptimizeCalcs    := MasterUnit.OptimizeCalculations;
+							CutRanges        := MasterUnit.CutUnusedRanges;
+							ReorderSections  := MasterUnit.ReorderSections;
+							MergeConstants   := MasterUnit.MergeConstants;
+						end;
+						OperationSuccessful := LinkLibLinkFiles (ObjectFileNames, ArchiveFileNames, LinkLibError, LinkLibGetOutputFile, nil, False, ProjectTarget = ptFlashOS, ProjectTarget = ptFargo, DataVarInfo, OptimizeInfo, not InitBSS) = 0;
+						if OperationSuccessful and (not OperationCancelled) then begin
+							if Pack and (ssPack in SpecialSupport) then begin
+								CompStartFile;
+								CompSetMessage ('Compressing');
+							end;
+							for CurCalcDest := FirstCalcDest to LastCalcDest do
+								if Assigned (LinkOutputFiles[CurCalcDest,frMain].Data) then
+									if OperationSuccessful and (not OperationCancelled) then begin
+										Include (CalcDests, CurCalcDest);
+										HandleContents (ProjectFile, FolderName, VarName, DataFolderName, DataVarName, Pack and (ssPack in SpecialSupport) and (CurCalcDest <> cdTI92), PackVar, CurCalcDest);
+									end;
+						end;
+					finally
+						for CurCalcDest := FirstCalcDest to LastCalcDest do begin
+							if Assigned (LinkOutputFiles[CurCalcDest,frMain].Data) then
+								LinkOutputFiles[CurCalcDest,frMain].Data.Free;
+							if Assigned (LinkOutputFiles[CurCalcDest,frData].Data) then
+								LinkOutputFiles[CurCalcDest,frData].Data.Free;
+							LinkOutputFiles[CurCalcDest,frMain].Data := nil;
+							LinkOutputFiles[CurCalcDest,frData].Data := nil;
+						end;
+					end;
+				end;
+			except
+				if Assigned (ArchiveFileNames) then
+					FreeMem (ArchiveFileNames);
+				if Assigned (ObjectFileNames) then
+					FreeMem (ObjectFileNames);
+				FileNameList.Free;
+			end;
+			if OperationSuccessful and (not OperationCancelled) and Pack and (ssPack in SpecialSupport) then
+				CreatePackStarter (ProjectFile, 'PStarter.o', FolderName, VarName, PackVar, CalcDests - [cdTI92]);
+			if OperationSuccessful and (not OperationCancelled) and (Length (PostBuildProcessFile) > 0) then begin
+				CompStartFile;
+				CompSetMessage ('Calling User-Defined Program');
+				MainConsole.Title := 'User-Defined Program';
+				S1 := PostBuildProcessFile;
+				P := Pos ('($TI89FILE)', UpperCase (S1));
+				if P > 0 then begin
+					Delete (S1, P, Length ('($TI89FILE)'));
+					if cdTI89 in CalcDests then
+						Insert (MainFiles [cdTI89], S1, P);
+				end;
+				P := Pos ('($TI92PLUSFILE)', UpperCase (S1));
+				if P > 0 then begin
+					Delete (S1, P, Length ('($TI92PLUSFILE)'));
+					if cdTI92Plus in CalcDests then
+						Insert (MainFiles [cdTI92Plus], S1, P);
+				end;
+				P := Pos ('($V200FILE)', UpperCase (S1));
+				if P > 0 then begin
+					Delete (S1, P, Length ('($V200FILE)'));
+					if cdV200 in CalcDests then
+						Insert (MainFiles [cdV200], S1, P);
+				end;
+				P := Pos ('($TI92FILE)', UpperCase (S1));
+				if P > 0 then begin
+					Delete (S1, P, Length ('($TI92FILE)'));
+					if cdTI92 in CalcDests then
+						Insert (MainFiles [cdTI92], S1, P);
+				end;
+				try
+					MainConsole.StartProcess ('', S1, '');
+					WaitForMainConsole ('User-Defined');
+				except
+					ShowDefaultMessageBox ('Could not start the user-defined program.', 'Error', mtProgramError);
+					OperationSuccessful := False;
+				end;
+				UpdateProgramOutput;
+			end;
+			if not OperationSuccessful then
+				ProgSize := 0;
+			CompUpdate;
+			try
+				if FileExists (Temp + 'TEMPPROG.PCK') then
+					DeleteFile (Temp + 'TEMPPROG.PCK');
+				if OperationSuccessful and (not OperationCancelled) and DeleteAssemblyFiles and (not DebugInfo) then
+					with SourceFiles do
+						for I := 0 to Count - 1 do
+							with TSourceFile (Items [I]) do
+								if InProject and (Items [I] is TCSourceFile) then
+									if FileExists (ChangeFileExt (FileName, '.s')) then
+										DeleteFile (ChangeFileExt (FileName, '.s'));
+				if OperationSuccessful and (not OperationCancelled) and DeleteObjectFiles then
+					with SourceFiles do
+						for I := 0 to Count - 1 do
+							with TSourceFile (Items [I]) do
+								if InProject and Compilable then begin
+									Invalidate;
+									if FileExists (ChangeFileExt (FileName, '.o')) then
+										DeleteFile (ChangeFileExt (FileName, '.o'));
+								end;
+			except end;
+			UpdateErrorWindow;
+			ShowErrors;
+			CompUpdate;
+			if OperationSuccessful and (not OperationCancelled) then begin
+				Invalidated := False;
+				CompUpdate;
+			end;
+		end else
+			ShowDefaultMessageBox ('Linker not loaded.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.FileOpenProject(Sender: TObject);
+begin
+	if OpenProjectDlg.Execute then begin
+		if LowerCase (ExtractFileExt (OpenProjectDlg.FileName)) = LowerCase (ProjectFileExt) then
+			FileOpen (ExpandFileName (OpenProjectDlg.FileName))
+		else
+			AddSourceFile (OpenProjectDlg.FileName, True);
+	end else
+		Abort;
+end;
+
+procedure TMainForm.FileSaveAll(Sender: TObject);
+begin
+	FileSave;
+end;
+
+procedure TMainForm.FileSaveProjectAs(Sender: TObject);
+begin
+	SaveProjectDlg.FileName := ProjectFile;
+	if SaveProjectDlg.Execute then
+		FileSaveAs (ExpandFileName (SaveProjectDlg.FileName))
+	else
+		Abort;
+end;
+
+procedure TMainForm.EditorKeyDown(Sender: TObject; var Key: Word;
+	Shift: TShiftState);
+var
+	I: Integer;
+	S: string;
+begin
+	if Key = vk_F1 then
+		if Sender is TMemoComponent then
+			with Sender as TMemoComponent do begin
+				S := '';
+				for I := Selection.RStart - 1 downto 1 do begin
+					if Text [I] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'] then
+						S := Text [I] + S
+					else
+						Break;
+				end;
+				for I := Selection.RStart to TextLength do begin
+					if Text [I] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'] then
+						S := S + Text [I]
+					else
+						Break;
+				end;
+				if S <> '' then begin
+					with SourceFiles do
+						for I := 0 to Count - 1 do
+							with Items [I] as TSourceFile do
+								if Assigned (ParentForm) then
+									ParentForm.WindowState := wsMinimized;
+					Application.ProcessMessages;
+					DocFile.KeywordLookup (S);
+				end;
+			end;
+end;
+
+procedure TMainForm.ProjectBuild(Sender: TObject);
+var
+	I: Integer;
+begin
+	if not Compiling then begin
+		if AutoSave then
+			FileSave
+		else
+			with SourceFiles do
+				for I := 0 to Count - 1 do
+					with Items [I] as TSourceFile do
+						if not InProject then
+							Save;
+		OperationSuccessful := False;
+		if ProjectFile = '' then
+			ShowDefaultMessageBox ('You need to save your project before you can create executable files.', 'Project not Saved', mtProgramError)
+		else begin
+			BeginCompilation;
+			RecompileFiles;
+			CompileProject;
+			Application.ProcessMessages;
+			if OperationSuccessful and not OperationCancelled then
+				MakeFile;
+			EndCompilation;
+			DisplayFolderMessage;
+		end;
+	end;
+end;
+
+procedure TMainForm.ProjectTreeKeyDown(Sender: TObject; var Key: Word;
+	Shift: TShiftState);
+begin
+	if (Key = vk_Delete) and not ProjectTree.IsEditing then
+		TreeItemRemove (Sender);
+end;
+
+procedure TMainForm.ProjectTreeMouseUp(Sender: TObject;
+	Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+begin
+	if Button = mbRight then
+		with ProjectTree do
+			if Assigned (Selected) then begin
+				if Assigned (Selected.Data) then begin
+					if TObject (Selected.Data) is TSourceFile then begin
+						with TSourceFile (Selected.Data) do begin
+							ActionTreeItemSave.Enabled := TSourceFile (Selected.Data) is TTextSourceFile;
+							ActionTreeItemSaveAs.Enabled := True;
+							ActionTreeItemCompile.Enabled := Compilable;
+						end;
+						with Mouse.CursorPos do
+							SourceFilePopup.Popup (X, Y);
+					end else if TObject (Selected.Data) is TFolder then begin
+						with Mouse.CursorPos do
+							FolderPopup.Popup (X, Y);
+					end;
+				end else if Assigned (Selected.Parent) then begin
+					with Mouse.CursorPos do
+						CategoryPopup.Popup (X, Y);
+				end;
+			end;
+end;
+
+procedure TMainForm.ProjectTreeEdited(Sender: TObject; Node: TTreeNode;
+	var S: String);
+var
+	I: Integer;
+	HasFolder,
+	NameConflict: Boolean;
+begin
+	if Node = TopNode then begin
+		if Length (S) <= 0 then
+			S := 'Project1'
+		else begin
+			HasFolder := False;
+			for I := Length (S) downto 1 do begin
+				if S [I] = '\' then begin
+					if HasFolder then
+						Delete (S, I, 1)
+					else
+						HasFolder := True;
+				end else if (not (IsCharAlphaNumeric (S [I]) or (S [I] in ['A'..'Z', 'a'..'z', '0'..'9']))) then
+					Delete (S, I, 1);
+			end;
+			if Length (S) <= 0 then
+				S := 'Project1'
+			else if not (IsCharAlpha (S [1]) or (S [1] in ['A'..'Z', 'a'..'z', '\'])) then
+				S := 'X' + S;
+			I := Pos ('\', S);
+			if I > 0 then begin
+				while I - 1 > MaxNameLength do begin
+					Delete (S, I - 1, 1);
+					Dec (I);
+				end;
+				while Length (S) - I > MaxNameLength do
+					Delete (S, Length (S), 1);
+				if I + 1 > Length (S) then
+					S := S + 'Project1'
+				else if I = 1 then
+					Delete (S, 1, 1)
+				else if not (IsCharAlpha (S [I + 1]) or (S [I + 1] in ['A'..'Z', 'a'..'z'])) then
+					Insert ('X', S, I + 1);
+			end else
+				S := Copy (S, 1, MaxNameLength);
+		end;
+		Modify;
+	end else begin
+		if Assigned (Node.Data) then begin
+			if (TObject (Node.Data) is TSourceFile) then begin
+				if S = '' then
+					S := 'File1';
+				NameConflict := False;
+				if TSourceFile(Node.Data).Compilable then
+					with SourceFiles do
+						for I := 0 to Count - 1 do
+							if Items [I] <> Node.Data then
+								with Items [I] as TSourceFile do
+									if Compilable and (LowerCase (SourceName) = LowerCase (S)) and (WithoutBackslash (FolderPath) = WithoutBackslash (TSourceFile(Node.Data).FolderPath)) then begin
+										NameConflict := True;
+										Break;
+									end;
+				if not NameConflict then try
+					if Assigned (Node.Data) then
+						TSourceFile(Node.Data).SourceName := S;
+					Modify;
+					Exit;
+				except end;
+				S := Node.Text;
+				ShowDefaultMessageBox ('The name you chose conflicts with that of another file.', 'Error', mtProgramError)
+			end else begin
+				S := StringReplace (S, ' ', '', [rfReplaceAll]);
+				if Length (S) <= 0 then
+					S := Node.Text;
+				RecompileFiles;
+			end;
+		end;
+	end;
+end;
+
+procedure TMainForm.SetProjectFile(const Value: string);
+var
+	S: string;
+	B: Boolean;
+begin
+	FProjectFile := Value;
+	MasterUnit.ProjectFileName := Value;
+	if Value = '' then
+		Caption := OriginalCaption
+	else
+		Caption := OriginalCaption + ' - ' + WithoutExt (ExtractFileName (Value));
+	Application.Title := Caption;
+	if TopNode.Text = 'Project1' then begin
+		B := Modified;
+		S := WithoutExt (ExtractFileName (Value));
+		ProjectTreeEdited (ProjectTree, TopNode, S);
+		TopNode.Text := S;
+		Modified := B;
+	end;
+	S := ExtractFilePath (Value);
+	OpenProjectDlg.InitialDir := WithoutBackslash (S);
+	OpenProjectDlg.FileName := Value;
+	SaveProjectDlg.InitialDir := WithoutBackslash (S);
+	SaveProjectDlg.FileName := Value;
+	AddFileDlg.InitialDir := S;
+end;
+
+function TMainForm.AddSourceFile(const FN: string; OpenOnly: Boolean = False; SourceFileClass: TSourceFileClass = nil; Folder: TFolder = nil): TSourceFile;
+var
+	F: TForm;
+	S: string;
+	O: TOpenFileStatusForm;
+begin
+	if Compiling and (not OpenOnly) then
+		Result := nil
+	else begin
+		Result := SourceFiles.FindFile (FN);
+		if Assigned (Result) and Result.InProject then begin
+			Result := nil;
+			ShowDefaultMessageBox ('The file ''' + ExtractFileName (FN) + ''' is already included in the project.', 'File Already Included', mtProgramError);
+		end else if OpenOnly and Assigned (Result) then begin
+			Result := nil;
+			ShowDefaultMessageBox ('The file ''' + ExtractFileName (FN) + ''' has already been opened.', 'File Already Opened', mtProgramError);
+		end else if (not OpenOnly) and (LowerCase (ExtractFileExt (FN)) = '.qll') and (Assigned (SourceFiles.FindFileOfTypeInProject (TQuillSourceFile))) then begin
+			Result := nil;
+			ShowDefaultMessageBox ('There may be only one Quill source file in each project.', 'Quill Error', mtProgramError);
+		end else begin
+			if not Assigned (Result) then begin
+				O := nil;
+				try
+					if not OpeningProjectNow then begin
+						O := TOpenFileStatusForm.Create (Self);
+						S := ExtractFileName (FN);
+						O.FileNameLabel.Caption := 'Opening File ''' + Copy (S, 1, LastPos ('.', S) - 1) + '''...';
+						O.Show;
+						O.Update;
+					end;
+					if not Assigned (SourceFileClass) then
+						SourceFileClass := TSourceFile.GetAppropriateClassFromExt (ExtractFileExt (FN));
+					Result := SourceFileClass.Create (SourceFiles);
+					Result.Folder := Folder;
+					Result.LoadFromFile (FN, True);
+					Result.OnError := AddError;
+				finally
+					if Assigned (O) then
+						O.Free;
+				end;
+				if OpenOnly and (not Assigned (Result.Editor)) then begin
+					Result.Free;
+					Result := nil;
+					ShowDefaultMessageBox ('The file ''' + ExtractFileName (FN) + ''' is not a valid file for opening.', 'Invalid File', mtProgramError);
+				end;
+			end;
+			if Assigned (Result) then
+				with Result do begin
+					ErrorList := Self.ErrorList;
+					if OpenOnly then begin
+						if not Assigned (ParentForm) then begin
+							ParentForm := TSourceFileForm.Create (nil);
+							with ParentForm as TSourceFileForm do begin
+								Enabled := False;
+								SourceFile := Result;
+								Show;
+							end;
+							if Assigned (Editor) then
+								with Editor do begin
+									Parent := ParentForm;
+									Align := alClient;
+									Show;
+									if Enabled then
+										SetFocus;
+								end;
+						end;
+					end else begin
+						if Assigned (ParentForm) then begin
+							F := ParentForm;
+							ParentForm := nil;
+							F.Free;
+						end;
+						TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], Result);
+						with TreeItem do begin
+							ImageIndex    := ClassImageIndex;
+							SelectedIndex := ImageIndex;
+						end;
+					end;
+				end;
+		end;
+		if not OpeningProjectNow then
+			SortFiles;
+	end;
+end;
+
+procedure TMainForm.ProjectOptions(Sender: TObject);
+begin
+	with TProjectOptionsForm.Create (Self) do try
+		FlashOSRadioButton.Visible := ssFlashOS in SpecialSupport;
+		FargoRadioButton.Visible := ssFargo in SpecialSupport;
+		if ProjectTarget = ptArchive then
+			ArchiveRadioButton.Checked := True
+		else if (ProjectTarget = ptFlashOS) and (FlashOSRadioButton.Visible) then
+			FlashOSRadioButton.Checked := True
+		else if (ProjectTarget = ptFargo) and (FargoRadioButton.Visible) then
+			FargoRadioButton.Checked := True
+		else
+			ExecutableRadioButton.Checked := True;
+		DataVarCheckBox.Checked := UseDataVar;
+		DataVarEdit.Text := DataVar;
+		if DataVarCopy then begin
+			if DataVarCopyIfArchived then
+				DataVarCopyIfArchivedRadioButton.Checked := True
+			else
+				DataVarCopyAlwaysRadioButton.Checked := True;
+		end else
+			DataVarCopyNeverRadioButton.Checked := True;
+		PackCheckBox.Checked := Pack and (ssPack in SpecialSupport);
+		PackVarEdit.Text := PackVar;
+		GCCSwitchesEdit.Text := GCCSwitches;
+		AsSwitchesEdit.Text := AsSwitches;
+		AsmSwitchesEdit.Text := AsmSwitches;
+		DebugInfoCheckBox.Checked := DebugInfo;
+		OptimizeNOPsCheckBox.Checked := OptimizeNOPs;
+		OptimizeReturnsCheckBox.Checked := OptimizeReturns;
+		OptimizeBranchesCheckBox.Checked := OptimizeBranches;
+		OptimizeMovesCheckBox.Checked := OptimizeMoves;
+		OptimizeTestsCheckBox.Checked := OptimizeTests;
+		OptimizeCalculationsCheckBox.Checked := OptimizeCalculations;
+		RemoveUnusedSectionsCheckBox.Checked := RemoveUnusedSections;
+		CutUnusedRangesCheckBox.Checked := CutUnusedRanges;
+		ReorderSectionsCheckBox.Checked := ReorderSections;
+		MergeConstantsCheckBox.Checked := MergeConstants;
+		StdLibCheckBox.Checked := StdLib;
+		InitBSSCheckBox.Checked := InitBSS;
+		OutputBinCheckBox.Checked := OutputBin;
+		CommandLineEdit.Text := CommandLine;
+		ProcessFileEdit.Text := PostBuildProcessFile;
+		InitialLibOptions := PredefinedLibOptions;
+		if ShowModal = mrOK then begin
+			if ArchiveRadioButton.Checked then
+				ProjectTarget := ptArchive
+			else if FlashOSRadioButton.Checked then
+				ProjectTarget := ptFlashOS
+			else if FargoRadioButton.Checked then
+				ProjectTarget := ptFargo
+			else
+				ProjectTarget := ptRegular;
+			Pack := PackCheckBox.Checked;
+			PackVar := PackVarEdit.Text;
+			UseDataVar := DataVarCheckBox.Checked;
+			DataVar := DataVarEdit.Text;
+			DataVarCopy := False;
+			DataVarCopyIfArchived := False;
+			if DataVarCopyAlwaysRadioButton.Checked then
+				DataVarCopy := True
+			else if DataVarCopyIfArchivedRadioButton.Checked then begin
+				DataVarCopy := True;
+				DataVarCopyIfArchived := True;
+			end;
+			GCCSwitches := GCCSwitchesEdit.Text;
+			AsSwitches := AsSwitchesEdit.Text;
+			AsmSwitches := AsmSwitchesEdit.Text;
+			DebugInfo := DebugInfoCheckBox.Checked;
+			OptimizeNOPs := OptimizeNOPsCheckBox.Checked;
+			OptimizeReturns := OptimizeReturnsCheckBox.Checked;
+			OptimizeBranches := OptimizeBranchesCheckBox.Checked;
+			OptimizeMoves := OptimizeMovesCheckBox.Checked;
+			OptimizeTests := OptimizeTestsCheckBox.Checked;
+			OptimizeCalculations := OptimizeCalculationsCheckBox.Checked;
+			RemoveUnusedSections := RemoveUnusedSectionsCheckBox.Checked;
+			CutUnusedRanges := CutUnusedRangesCheckBox.Checked;
+			ReorderSections := ReorderSectionsCheckBox.Checked;
+			MergeConstants := MergeConstantsCheckBox.Checked;
+			StdLib := StdLibCheckBox.Checked;
+			InitBSS := InitBSSCheckBox.Checked;
+			OutputBin := OutputBinCheckBox.Checked;
+			CommandLine := CommandLineEdit.Text;
+			PostBuildProcessFile := ProcessFileEdit.Text;
+			if Assigned (ProgramOptionsForm) and Assigned (PredefinedLibOptions) then
+				with ProgramOptionsForm, PredefinedLibOptions do begin
+					CalcDests := [];
+					if TI89CheckBox.Checked then
+						Include (CalcDests, cdTI89);
+					if TI92PlusCheckBox.Checked then
+						Include (CalcDests, cdTI92Plus);
+					if V200CheckBox.Checked then
+						Include (CalcDests, cdV200);
+					OptimizeCalcConsts := OptimizeCalcConstsCheckBox.Checked;
+					if PreOsRadioButton.Checked then
+						KernelFormat := kfCompressedTables
+					else if DoorsRadioButton.Checked then
+						KernelFormat := kfStandard
+					else
+						KernelFormat := kfNone;
+					UseMinAMS := MinAMSCheckBox.Checked;
+					if Length (MinAMSEdit.Text) > 0 then
+						MinAMS := MinAMSEdit.Text;
+					UnofficialOSSupport := UnofficialOSSupportCheckBox.Checked;
+					if RelocKernelRadioButton.Checked then
+						RelocFormat := rfKernel
+					else if RelocCompressedRadioButton.Checked then
+						RelocFormat := rfCompressed
+					else
+						RelocFormat := rfAMS;
+					if ROMCallKernelRadioButton.Checked then
+						ROMCallFormat := rfKernel
+					else if ROMCallCompressedRadioButton.Checked then
+						ROMCallFormat := rfCompressed
+					else if ROMCallFLineRadioButton.Checked then
+						ROMCallFormat := rfFLine
+					else
+						ROMCallFormat := rfDirect;
+					if BSSKernelRadioButton.Checked then
+						BSSRefFormat := rfKernel
+					else if BSSCompressedRadioButton.Checked then
+						BSSRefFormat := rfCompressed
+					else
+						BSSRefFormat := rfNone;
+					if DataVarKernelRadioButton.Checked then
+						DataRefFormat := rfKernel
+					else if DataVarCompressedRadioButton.Checked then
+						DataRefFormat := rfCompressed
+					else
+						DataRefFormat := rfNone;
+					UseFLineJumps      := RelocFLineJumpsCheckBox.Checked;
+					Use4ByteFLineJumps := RelocFLineJumps4ByteCheckBox.Checked;
+					OptimizeROMCalls := ROMCallOptimizedCheckBox.Checked;
+					UseInternalFLineEmulator := InternalFLineEmulatorCheckBox.Checked;
+					UseReturnValue           := ReturnValueRadioButton.Checked;
+					EnableErrorReturn        := EnableErrorReturnCheckBox.Checked;
+					SaveScreen               := LCDSaveCheckBox.Checked;
+				end;
+			RecompileFiles;
+			if not DebugInfo then
+				ClearDebugInfo;
+			UpdateDebugSettings;
+			Modify;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.FilePreferences(Sender: TObject);
+var
+	I: Integer;
+begin
+	with TPreferencesForm.Create (Self) do try
+		StopCompilationBox.Checked := StopOnErrors;
+		JumpToErrorBox.Checked := JumpToError;
+		OpenFolderBox.Checked := OpenFolderMessage;
+		DeleteAssemblyFilesBox.Checked := DeleteAssemblyFiles;
+		DeleteObjectFilesBox.Checked := DeleteObjectFiles;
+{$IFDEF CanSplit}
+		SplitFilesCheckBox.Checked := SplitFiles;
+{$ENDIF}
+		AutoSaveCheckBox.Checked := AutoSave;
+		AutoNewsCheckBox.Checked := AutoNews;
+		DeleteErrorsCheckBox.Checked := DeleteErrors;
+		AllowImplicitCheckBox.Checked := not AssumeUndefined;
+		FlatButtonsCheckBox.Checked := MainToolbar.Flat;
+		MenuBitmapsCheckBox.Checked := Assigned (MainMenu.Images);
+		case TransferTarget of
+			ttVTI:
+				VTIBox.Checked := True;
+			ttCalc:
+				RealCalcBox.Checked := True;
+			else
+				NoneBox.Checked := True;
+		end;
+		VTIPathEdit.Text := VTIPath;
+		case LinkPort.PortType of
+			lpCOM: begin
+				case LinkPort.PortNumber of
+					1: PortCOM1Box.Checked := True;
+					2: PortCOM2Box.Checked := True;
+					3: PortCOM3Box.Checked := True;
+					4: PortCOM4Box.Checked := True;
+				end;
+			end;
+		end;
+		case LinkCable of
+			lcBlack: CableBlackBox.Checked := True;
+			lcGray:  CableGrayBox.Checked := True;
+		end;
+		AsmTabSizeEdit.Text := IntToStr (TabSizeAsm);
+		CTabSizeEdit.Text := IntToStr (TabSizeC);
+		BackColor := EditorColor;
+		ColorCheckBox.Checked := BackColor <> clWindow;
+		EditorFont.Assign (MasterUnit.EditorFont);
+		OnFlyCheckBox.Checked := EditorOnFly;
+		DragDropEditCheckBox.Checked := EditorDragDrop;
+		RemoveTrailingSpcCheckBox.Checked := EditorRemoveTrSp;
+		AutoBlockCheckBox.Checked := AutoBlocks;
+		SyntaxC.Assign (MasterUnit.SyntaxC);
+		SyntaxAsmGNU.Assign (MasterUnit.SyntaxAsmGNU);
+		if ssA68k in SpecialSupport then
+			SyntaxAsm.Assign (MasterUnit.SyntaxAsm);
+		if ssQuill in SpecialSupport then
+			SyntaxQuill.Assign (MasterUnit.SyntaxQuill);
+		if ShowModal = mrOK then begin
+			Screen.Cursor := crHourGlass;
+			StopOnErrors := StopCompilationBox.Checked;
+			JumpToError := JumpToErrorBox.Checked;
+			OpenFolderMessage := OpenFolderBox.Checked;
+			DeleteAssemblyFiles := DeleteAssemblyFilesBox.Checked;
+			DeleteObjectFiles := DeleteObjectFilesBox.Checked;
+{$IFDEF CanSplit}
+			SplitFiles := SplitFilesCheckBox.Checked;
+{$ENDIF}
+			AutoSave := AutoSaveCheckBox.Checked;
+			AutoNews := AutoNewsCheckBox.Checked;
+			DeleteErrors := DeleteErrorsCheckBox.Checked;
+			AssumeUndefined := not AllowImplicitCheckBox.Checked;
+			MainToolbar.Flat := FlatButtonsCheckBox.Checked;
+			if MainToolbar.Flat then
+				MainToolbar.Height := MainToolbar.ButtonHeight + 1
+			else
+				MainToolbar.Height := MainToolbar.ButtonHeight + 3;
+			if MenuBitmapsCheckBox.Checked then
+				MainMenu.Images := ToolbarImages
+			else
+				MainMenu.Images := nil;
+			if VTIBox.Checked then
+				TransferTarget := ttVTI
+			else if RealCalcBox.Checked then
+				TransferTarget := ttCalc
+			else
+				TransferTarget := ttNone;
+			VTIPath := VTIPathEdit.Text;
+			LinkPort.PortType := lpCOM;
+			if PortCOM1Box.Checked then
+				LinkPort.PortNumber := 1
+			else if PortCOM2Box.Checked then
+				LinkPort.PortNumber := 2
+			else if PortCOM3Box.Checked then
+				LinkPort.PortNumber := 3
+			else if PortCOM4Box.Checked then
+				LinkPort.PortNumber := 4;
+			if CableBlackBox.Checked then
+				LinkCable := lcBlack
+			else if CableGrayBox.Checked then
+				LinkCable := lcGray;
+			try
+				TabSizeC := StrToInt (CTabSizeEdit.Text);
+			except
+				TabSizeC := 2;
+			end;
+			try
+				TabSizeAsm := StrToInt (AsmTabSizeEdit.Text);
+			except
+				TabSizeAsm := 2;
+			end;
+			if ColorCheckBox.Checked then
+				EditorColor := BackColor
+			else
+				EditorColor := clWindow;
+			MasterUnit.EditorFont.Assign (EditorFont);
+			EditorOnFly := OnFlyCheckBox.Checked;
+			EditorDragDrop := DragDropEditCheckBox.Checked;
+			EditorRemoveTrSp := RemoveTrailingSpcCheckBox.Checked;
+			AutoBlocks := AutoBlockCheckBox.Checked;
+			with SourceFiles do
+				for I := 0 to Count - 1 do
+					if Items [I] is TTextSourceFile then
+						(Items [I] as TTextSourceFile).UpdateEditor;
+			if SyntaxTabClicked then begin
+				MasterUnit.SyntaxC.Assign (SyntaxC);
+				MasterUnit.SyntaxAsmGNU.Assign (SyntaxAsmGNU);
+				MasterUnit.SyntaxAsm.Assign (SyntaxAsm);
+				MasterUnit.SyntaxQuill.Assign (SyntaxQuill);
+				with SourceFiles do
+					for I := 0 to Count - 1 do
+						if Items [I] is TSourceTextSourceFile then
+							(Items [I] as TSourceTextSourceFile).UpdateSyntax;
+			end;
+			SavePreferences;
+			UpdateDebugSettings;
+			Screen.Cursor := crDefault;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.LoadPreferences;
+function LookBackForComponent(Stream: TMemoryStream): Integer;
+var
+	I: Integer;
+	P: PChar;
+begin
+	Result := 0;
+	with Stream do begin
+		P := Memory;
+		for I := Size - 3 downto 1 do
+			if (P [I] = 'T') and (P [I + 1] = 'P') and (P [I + 2] = 'F') then begin
+				Result := I;
+				Break;
+			end;
+	end;
+end;
+var
+	I,
+	Tmp: Integer;
+	L: TStringList;
+	Strm: TMemoryStream;
+	SyntaxCopy: TSyntaxColoringCopy;
+begin
+	with TRegistry.Create do try
+		if OpenKeyReadOnly (RegKey) then try
+			if ValueExists ('Open File') then
+				ProjectFile := ReadString ('Open File');
+			if ValueExists ('Recent Files') then begin
+				L := TStringList.Create;
+				try
+					L.CommaText := ReadString ('Recent Files');
+					for I := L.Count - 1 downto 0 do
+						AddToRecent (L.Strings [I]);
+				finally
+					L.Free;
+				end;
+			end;
+			if ValueExists ('Stop on Errors') then
+				StopOnErrors := ReadBool ('Stop on Errors');
+			if ValueExists ('Jump To First Error') then
+				JumpToError := ReadBool ('Jump To First Error');
+			if ValueExists ('Open Folder Message') then
+				OpenFolderMessage := ReadBool ('Open Folder Message');
+			if ValueExists ('Delete Assembly Files') then
+				DeleteAssemblyFiles := ReadBool ('Delete Assembly Files');
+			if ValueExists ('Delete Object Files') then
+				DeleteObjectFiles := ReadBool ('Delete Object Files');
+{$IFDEF CanSplit}
+			if ValueExists ('Split Files') then
+				SplitFiles := ReadBool ('Split Files');
+{$ENDIF}
+			if ValueExists ('AutoSave') then
+				AutoSave := ReadBool ('AutoSave');
+			if ValueExists ('AutoNews') then
+				AutoNews := ReadBool ('AutoNews');
+			if ValueExists ('Delete Errors') then
+				DeleteErrors := ReadBool ('Delete Errors');
+			if ValueExists ('Assume Undefined References') then
+				AssumeUndefined := ReadBool ('Assume Undefined References');
+			if ValueExists ('Flat Buttons') then
+				MainToolbar.Flat := ReadBool ('Flat Buttons');
+			if MainToolbar.Flat then
+				MainToolbar.Height := MainToolbar.ButtonHeight + 1
+			else
+				MainToolbar.Height := MainToolbar.ButtonHeight + 3;
+			if ValueExists ('Menu Bitmaps') then begin
+				if ReadBool ('Menu Bitmaps') then
+					MainMenu.Images := ToolbarImages
+				else
+					MainMenu.Images := nil;
+			end;
+			if ValueExists ('Transfer Target') then
+				TransferTarget := TTransferTarget (ReadInteger ('Transfer Target') + 1);
+			if ValueExists ('VTI Path') then
+				VTIPath := ReadString ('VTI Path');
+			if ValueExists ('Link Port') then
+				LinkPort.PortNumber := ReadInteger ('Link Port') and $FF;
+			if ValueExists ('Link Cable') then begin
+				if ReadInteger ('Link Cable') = 2 then
+					LinkCable := lcGray
+				else
+					LinkCable := lcBlack;
+			end;
+			if ValueExists ('ASM Tab Size') then
+				TabSizeAsm := ReadInteger ('ASM Tab Size');
+			if ValueExists ('C Tab Size') then
+				TabSizeC := ReadInteger ('C Tab Size');
+			if ValueExists ('Editor Background Color') then
+				EditorColor := ReadInteger ('Editor Background Color');
+			if ValueExists ('Editor Font') then
+				EditorFont.Name := ReadString ('Editor Font');
+			if ValueExists ('Editor Font Style Bold') then begin
+				EditorFont.Style := [];
+				if ReadBool ('Editor Font Style Bold') then
+					EditorFont.Style := EditorFont.Style + [fsBold];
+				if ReadBool ('Editor Font Style Italic') then
+					EditorFont.Style := EditorFont.Style + [fsItalic];
+				if ReadBool ('Editor Font Style Underline') then
+					EditorFont.Style := EditorFont.Style + [fsUnderline];
+				if ReadBool ('Editor Font Style StrikeOut') then
+					EditorFont.Style := EditorFont.Style + [fsStrikeOut];
+			end;
+			if ValueExists ('Editor Font Size') then
+				EditorFont.Size := ReadInteger ('Editor Font Size');
+			if ValueExists ('Editor Font Color') then
+				EditorFont.Color := ReadInteger ('Editor Font Color');
+			if ValueExists ('Editor Font Pitch') then
+				EditorFont.Pitch := TFontPitch (ReadInteger ('Editor Font Pitch'));
+			if ValueExists ('Editor Split On Fly') then
+				EditorOnFly := ReadBool ('Editor Split On Fly');
+			if ValueExists ('Editor Drag and Drop') then
+				EditorDragDrop := ReadBool ('Editor Drag and Drop');
+			if ValueExists ('Editor Remove Trailing Spaces') then
+				EditorRemoveTrSp := ReadBool ('Editor Remove Trailing Spaces');
+			if ValueExists ('AutoBlocks') then
+				AutoBlocks := ReadBool ('AutoBlocks');
+			if ValueExists ('Tree Width') then
+				ProjectTree.Width := ReadInteger ('Tree Width');
+			if ValueExists ('Error Window Height') then
+				ErrWinPanel.Height := ReadInteger ('Error Window Height');
+			if ValueExists ('Error List Message') then
+				ErrorList.Columns[0].Width := ReadInteger ('Error List Message');
+			if ValueExists ('Error List File') then
+				ErrorList.Columns[1].Width := ReadInteger ('Error List File');
+			if ValueExists ('Error List Function') then
+				ErrorList.Columns[2].Width := ReadInteger ('Error List Function');
+			if ValueExists ('Last News Update') then
+				LastNewsDate := ReadInteger ('Last News Update');
+			if ValueExists ('Proxy Name') then
+				ProxyName := ReadString ('Proxy Name');
+			if ValueExists ('Proxy Port') then
+				ProxyPort := ReadInteger ('Proxy Port');
+			Strm := TMemoryStream.Create;
+			if ValueExists ('Editor C Syntax Coloring') then try
+				SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+				try
+					SyntaxCopy.Assign (SyntaxC);
+					Strm.SetSize (GetDataSize ('Editor C Syntax Coloring'));
+					if Strm.Size > 0 then begin
+						ReadBinaryData ('Editor C Syntax Coloring', Strm.Memory^, Strm.Size);
+						Strm.Position := LookBackForComponent (Strm);
+						Strm.ReadComponent (SyntaxCopy);
+						SyntaxC.Assign (SyntaxCopy);
+					end;
+				finally
+					SyntaxCopy.Free;
+				end;
+			except end;
+			if ValueExists ('Editor GNU ASM Syntax Coloring') then try
+				SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+				try
+					SyntaxCopy.Assign (SyntaxAsmGNU);
+					Strm.SetSize (GetDataSize ('Editor GNU ASM Syntax Coloring'));
+					if Strm.Size > 0 then begin
+						ReadBinaryData ('Editor GNU ASM Syntax Coloring', Strm.Memory^, Strm.Size);
+						Strm.Position := LookBackForComponent (Strm);
+						Strm.ReadComponent (SyntaxCopy);
+						SyntaxAsmGNU.Assign (SyntaxCopy);
+					end;
+				finally
+					SyntaxCopy.Free;
+				end;
+			except end;
+			if (ssA68k in SpecialSupport) and ValueExists ('Editor ASM Syntax Coloring') then try
+				SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+				try
+					SyntaxCopy.Assign (SyntaxAsm);
+					Strm.SetSize (GetDataSize ('Editor ASM Syntax Coloring'));
+					if Strm.Size > 0 then begin
+						ReadBinaryData ('Editor ASM Syntax Coloring', Strm.Memory^, Strm.Size);
+						Strm.Position := LookBackForComponent (Strm);
+						Strm.ReadComponent (SyntaxCopy);
+						SyntaxAsm.Assign (SyntaxCopy);
+					end;
+				finally
+					SyntaxCopy.Free;
+				end;
+			except end;
+			if (ssQuill in SpecialSupport) and ValueExists ('Editor Quill Syntax Coloring') then try
+				SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+				try
+					SyntaxCopy.Assign (SyntaxQuill);
+					Strm.SetSize (GetDataSize ('Editor Quill Syntax Coloring'));
+					if Strm.Size > 0 then begin
+						ReadBinaryData ('Editor Quill Syntax Coloring', Strm.Memory^, Strm.Size);
+						Strm.Position := LookBackForComponent (Strm);
+						Strm.ReadComponent (SyntaxCopy);
+						SyntaxQuill.Assign (SyntaxCopy);
+					end;
+				finally
+					SyntaxCopy.Free;
+				end;
+			except end;
+			Strm.Free;
+			if ValueExists ('Tools Count') then begin
+				Tmp := ReadInteger ('Tools Count');
+				ToolsList.Clear;
+				for I := 1 to Tmp do
+					if OpenKeyReadOnly (RegKey + '\Tool ' + IntToStr (I)) then try
+						ToolsLine.Visible := True;
+						AddTool (ReadString ('Title'), ReadString ('Command Line'), ReadString ('Working Directory'), TWindowState (ReadInteger ('Window State')));
+					except end;
+			end;
+		except end;
+	finally
+		Free;
+		SplitterMoved (Self);
+	end;
+	with SourceFiles do
+		for I := 0 to Count - 1 do begin
+			if Items [I] is TTextSourceFile then
+				(Items [I] as TTextSourceFile).UpdateEditor;
+			if Items [I] is TSourceTextSourceFile then
+				(Items [I] as TSourceTextSourceFile).UpdateSyntax;
+		end;
+	UpdateDebugSettings;
+end;
+
+procedure TMainForm.SavePreferences;
+var
+	I: Integer;
+	Strm: TMemoryStream;
+	SyntaxCopy: TSyntaxColoringCopy;
+begin
+	with TRegistry.Create do try
+		if OpenKey (RegKey, True) then try
+			WriteString ('Open File', ProjectFile);
+			WriteString ('Recent Files', RecentFiles.CommaText);
+			WriteBool ('Stop on Errors', StopOnErrors);
+			WriteBool ('Jump To First Error', JumpToError);
+			WriteBool ('Open Folder Message', OpenFolderMessage);
+			WriteBool ('Delete Assembly Files', DeleteAssemblyFiles);
+			WriteBool ('Delete Object Files', DeleteObjectFiles);
+{$IFDEF CanSplit}
+			WriteBool ('Split Files', SplitFiles);
+{$ENDIF}
+			WriteBool ('AutoSave', AutoSave);
+			WriteBool ('AutoNews', AutoNews);
+			WriteBool ('Delete Errors', DeleteErrors);
+			WriteBool ('Assume Undefined References', AssumeUndefined);
+			WriteBool ('Flat Buttons', MainToolbar.Flat);
+			WriteBool ('Menu Bitmaps', Assigned (MainMenu.Images));
+			WriteInteger ('Transfer Target', Integer (TransferTarget) - 1);
+			WriteString ('VTI Path', VTIPath);
+			WriteInteger ('Link Port', LinkPort.PortNumber);
+			case LinkCable of
+				lcBlack: WriteInteger ('Link Cable', 1);
+				lcGray:  WriteInteger ('Link Cable', 2);
+			end;
+			WriteInteger ('ASM Tab Size', TabSizeAsm);
+			WriteInteger ('C Tab Size', TabSizeC);
+			WriteInteger ('Editor Background Color', EditorColor);
+			WriteString ('Editor Font', EditorFont.Name);
+			WriteBool ('Editor Font Style Bold', fsBold in EditorFont.Style);
+			WriteBool ('Editor Font Style Italic', fsItalic in EditorFont.Style);
+			WriteBool ('Editor Font Style Underline', fsUnderline in EditorFont.Style);
+			WriteBool ('Editor Font Style StrikeOut', fsStrikeOut in EditorFont.Style);
+			WriteInteger ('Editor Font Size', EditorFont.Size);
+			WriteInteger ('Editor Font Color', EditorFont.Color);
+			WriteInteger ('Editor Font Pitch', Integer (EditorFont.Pitch));
+			WriteBool ('Editor Split On Fly', EditorOnFly);
+			WriteBool ('Editor Drag and Drop', EditorDragDrop);
+			WriteBool ('Editor Remove Trailing Spaces', EditorRemoveTrSp);
+			WriteBool ('AutoBlocks', AutoBlocks);
+			WriteInteger ('Tree Width', ProjectTree.Width);
+			WriteInteger ('Error Window Height', ErrWinPanel.Height);
+			WriteInteger ('Error List Message', ErrorList.Columns[0].Width);
+			WriteInteger ('Error List File', ErrorList.Columns[1].Width);
+			WriteInteger ('Error List Function', ErrorList.Columns[2].Width);
+			WriteInteger ('Last News Update', LastNewsDate);
+			WriteString ('Proxy Name', ProxyName);
+			WriteInteger ('Proxy Port', ProxyPort);
+			Strm := TMemoryStream.Create;
+			try
+				SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+				try
+					SyntaxCopy.Assign (SyntaxC);
+					Strm.WriteComponent (SyntaxCopy);
+					WriteBinaryData ('Editor C Syntax Coloring', Strm.Memory^, Strm.Size);
+				finally
+					SyntaxCopy.Free;
+				end;
+				Strm.Clear;
+				SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+				try
+					SyntaxCopy.Assign (SyntaxAsmGNU);
+					Strm.WriteComponent (SyntaxCopy);
+					WriteBinaryData ('Editor GNU ASM Syntax Coloring', Strm.Memory^, Strm.Size);
+				finally
+					SyntaxCopy.Free;
+				end;
+				if ssA68k in SpecialSupport then begin
+					Strm.Clear;
+					SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+					try
+						SyntaxCopy.Assign (SyntaxAsm);
+						Strm.WriteComponent (SyntaxCopy);
+						WriteBinaryData ('Editor ASM Syntax Coloring', Strm.Memory^, Strm.Size);
+					finally
+						SyntaxCopy.Free;
+					end;
+				end;
+				if ssQuill in SpecialSupport then begin
+					Strm.Clear;
+					SyntaxCopy := TSyntaxColoringCopy.Create (nil);
+					try
+						SyntaxCopy.Assign (SyntaxQuill);
+						Strm.WriteComponent (SyntaxCopy);
+						WriteBinaryData ('Editor Quill Syntax Coloring', Strm.Memory^, Strm.Size);
+					finally
+						SyntaxCopy.Free;
+					end;
+				end;
+			finally
+				Strm.Free;
+			end;
+			WriteInteger ('Tools Count', ToolsList.Count);
+			with ToolsList do
+				for I := 0 to Count - 1 do
+					with TToolsListItem (Items [I]) do
+						if OpenKey (RegKey + '\Tool ' + IntToStr (I + 1), True) then try
+							WriteString ('Title', Title);
+							WriteString ('Command Line', CommandLine);
+							WriteString ('Working Directory', WorkingDir);
+							WriteInteger ('Window State', Integer (WindowState));
+						except end;
+		except end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.CompileProject;
+var
+	I: Integer;
+	StopIt: Boolean;
+begin
+	OperationSuccessful := False;
+	OperationCancelled := False;
+	StopIt := True;
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			with Items [I] as TSourceFile do
+				if Compilable or (Items [I] is TObjectSourceFile) then begin
+					StopIt := False;
+					Break;
+				end;
+	if not StopIt then begin
+		OperationSuccessful := True;
+		CopyHeaders;
+		with SourceFiles do
+			for I := 0 to Count - 1 do
+				if (OperationSuccessful or not StopOnErrors) and not OperationCancelled then
+					with Items [I] as TSourceFile do
+						if Compilable and Invalidated then begin
+							Compile;
+							if not OperationSuccessful then
+								StopIt := True;
+							Application.ProcessMessages;
+						end;
+		DeleteHeaders;
+		if StopIt then
+			OperationSuccessful := False;
+	end else
+		ShowDefaultMessageBox ('There are no files to compile in the current project.', 'Error', mtProgramError);
+end;
+
+function TMainForm.GetNewFileName(const FolderPath, Ext: string): string;
+var
+	I: Integer;
+begin
+	if ProjectFile = '' then
+		Result := 'C:\New File'
+	else
+		Result := WithBackslash (ExtractFilePath (ProjectFile) + FolderPath) + 'New File';
+	if FileExists (Result + Ext) or Assigned (SourceFiles.FindFileWithoutExt (Result)) then begin
+		I := 2;
+		while FileExists (Result + ' ' + IntToStr (I) + Ext) or Assigned (SourceFiles.FindFileWithoutExt (Result + ' ' + IntToStr (I))) do
+			Inc (I);
+		Result := Result + ' ' + IntToStr (I);
+	end;
+	Result := Result + Ext;
+end;
+
+procedure TMainForm.FileNewHeaderFile(Sender: TObject);
+var
+	O: THeaderSourceFile;
+begin
+	if not Compiling then begin
+		O := THeaderSourceFile.Create (SourceFiles);
+		with O do begin
+			Folder := GetSelectedFolder (THeaderSourceFile);
+			FileName := GetNewFileName (FolderPath, '.h');
+			OnError := AddError;
+			TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], O);
+			with TreeItem do begin
+				ImageIndex    := ClassImageIndex;
+				SelectedIndex := ImageIndex;
+			end;
+			ErrorList := Self.ErrorList;
+			if Assigned (TextEditor) then
+				with TextEditor do begin
+					Hide;
+					Parent := EditorPanel;
+					Align := alClient;
+					OnEnter := EditorEnter;
+					OnExit := EditorExit;
+					OnKeyDown := EditorKeyDown;
+					OnChange := EditorChange;
+					OnSelectionChange := EditorChange;
+					PopupMenu := EditorPopup;
+				end;
+			if (Sender = ActionFileNewGNUAsmHeaderFile) or ((Sender is TMenuItem) and (TMenuItem(Sender).Action = ActionFileNewGNUAsmHeaderFile)) then
+				Content := '| Header File'#13#10'| Created ' + DateToStr (Now) + '; ' + TimeToStr (Now) + #13#10
+			else if (Sender = ActionFileNewA68kAsmHeaderFile) or ((Sender is TMenuItem) and (TMenuItem(Sender).Action = ActionFileNewA68kAsmHeaderFile)) then
+				Content := '; Header File'#13#10'; Created ' + DateToStr (Now) + '; ' + TimeToStr (Now) + #13#10
+			else
+				Content := '// Header File'#13#10'// Created ' + DateToStr (Now) + '; ' + TimeToStr (Now) + #13#10;
+			UpdateSyntax;
+			if Assigned (TextEditor) then
+				TextEditor.ClearUndo;
+			Modified := False;
+			Invalidate;
+			SelectNode (TreeItem);
+			TreeItem.EditText;
+		end;
+	end;
+end;
+
+procedure TMainForm.FileNewCSourceFile(Sender: TObject);
+const
+	CodeStr = '// Place your code here.';
+var
+	O: TCSourceFile;
+	I,
+	P: Integer;
+	NewContent: string;
+	FirstFile: Boolean;
+begin
+	if not Compiling then begin
+		FirstFile := not Assigned (SourceFiles.FindFileOfTypeInProject (TCSourceFile));
+		O := TCSourceFile.Create (SourceFiles);
+		with O do begin
+			Folder := GetSelectedFolder (TCSourceFile);
+			FileName := GetNewFileName (FolderPath, '.c');
+			OnError := AddError;
+			TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], O);
+			with TreeItem do begin
+				ImageIndex    := ClassImageIndex;
+				SelectedIndex := ImageIndex;
+			end;
+			ErrorList := Self.ErrorList;
+			if Assigned (TextEditor) then
+				with TextEditor do begin
+					Hide;
+					Parent := EditorPanel;
+					Align := alClient;
+					OnEnter := EditorEnter;
+					OnExit := EditorExit;
+					OnKeyDown := EditorKeyDown;
+					OnChange := EditorChange;
+					OnSelectionChange := EditorChange;
+					PopupMenu := EditorPopup;
+				end;
+			NewContent := '// C Source File'#13#10'// Created ' + DateToStr (Now) + '; ' + TimeToStr (Now) + #13#10;
+			case ProjectTarget of
+				ptRegular: begin
+					if FirstFile then begin
+						NewContent := NewContent + #13#10
+							+ '// Delete or comment out the items you do not need.'#13#10
+							+ '#define COMMENT_STRING         "Place your comment here."'#13#10
+							+ '#define COMMENT_PROGRAM_NAME   "Place your program name here."'#13#10
+							+ '#define COMMENT_VERSION_STRING "Place your version string here."'#13#10
+							+ '#define COMMENT_VERSION_NUMBER 0,0,0,0 /* major, minor, revision, subrevision */'#13#10
+							+ '#define COMMENT_BW_ICON \'#13#10
+							+ #9'{0b0000000000000000, \'#13#10;
+						for I := 1 to 14 do
+							NewContent := NewContent
+								+ #9' 0b0000000000000000, \'#13#10;
+						NewContent := NewContent
+							+ #9' 0b0000000000000000}'#13#10
+							+ '#define COMMENT_GRAY_ICON \'#13#10
+							+ #9'{0b0000000000000000, \'#13#10;
+						for I := 1 to 14 do
+							NewContent := NewContent
+								+ #9' 0b0000000000000000, \'#13#10;
+						NewContent := NewContent
+							+ #9' 0b0000000000000000}, \'#13#10
+							+ #9'{0b0000000000000000, \'#13#10;
+						for I := 1 to 14 do
+							NewContent := NewContent
+								+ #9' 0b0000000000000000, \'#13#10;
+						NewContent := NewContent
+							+ #9' 0b0000000000000000}'#13#10;
+					end;
+					NewContent := NewContent + #13#10'#include <tigcclib.h>'#13#10;
+				end;
+				ptArchive:
+					NewContent := NewContent + #13#10'#define _GENERIC_ARCHIVE'#13#10'#include <tigcclib.h>'#13#10;
+			end;
+			if FirstFile and (not (ProjectTarget in [ptFlashOS, ptArchive])) then
+				NewContent := NewContent + #13#10'// Main Function'#13#10'void _main(void)'#13#10
+					+ '{'#13#10
+					+ #9 + CodeStr + #13#10
+					+ '}'#13#10;
+			if Assigned (TextEditor) then
+				TextEditor.AllowUndo := False;
+			Content := NewContent;
+			if Assigned (TextEditor) then begin
+				TextEditor.AllowUndo := True;
+				P := Pos (CodeStr, TextEditor.Text);
+				if P > 0 then
+					with TextEditor.Selection do begin
+						RStart := P;
+						RLength := Length (CodeStr);
+					end;
+			end;
+			Modified := False;
+			Invalidate;
+			SelectNode (TreeItem);
+			TreeItem.EditText;
+		end;
+	end;
+end;
+
+procedure TMainForm.FileNewGNUAssemblerSourceFile(Sender: TObject);
+var
+	O: TGNUAsmSourceFile;
+begin
+	if not Compiling then begin
+		O := TGNUAsmSourceFile.Create (SourceFiles);
+		with O do begin
+			Folder := GetSelectedFolder (TGNUAsmSourceFile);
+			FileName := GetNewFileName (FolderPath, '.s');
+			OnError := AddError;
+			TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], O);
+			with TreeItem do begin
+				ImageIndex    := ClassImageIndex;
+				SelectedIndex := ImageIndex;
+			end;
+			ErrorList := Self.ErrorList;
+			if Assigned (TextEditor) then
+				with TextEditor do begin
+					Hide;
+					Parent := EditorPanel;
+					Align := alClient;
+					OnEnter := EditorEnter;
+					OnExit := EditorExit;
+					OnKeyDown := EditorKeyDown;
+					OnChange := EditorChange;
+					OnSelectionChange := EditorChange;
+					PopupMenu := EditorPopup;
+				end;
+			Content := '| Assembly Source File'#13#10'| Created ' + DateToStr (Now) + '; ' + TimeToStr (Now) + #13#10;
+			if Assigned (TextEditor) then
+				TextEditor.ClearUndo;
+			Modified := False;
+			Invalidate;
+			SelectNode (TreeItem);
+			TreeItem.EditText;
+		end;
+	end;
+end;
+
+procedure TMainForm.FileNewAssemblerSourceFile(Sender: TObject);
+var
+	O: TAsmSourceFile;
+begin
+	if not Compiling then begin
+		O := TAsmSourceFile.Create (SourceFiles);
+		with O do begin
+			Folder := GetSelectedFolder (TAsmSourceFile);
+			FileName := GetNewFileName (FolderPath, '.asm');
+			OnError := AddError;
+			TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], O);
+			with TreeItem do begin
+				ImageIndex    := ClassImageIndex;
+				SelectedIndex := ImageIndex;
+			end;
+			ErrorList := Self.ErrorList;
+			if Assigned (TextEditor) then
+				with TextEditor do begin
+					Hide;
+					Parent := EditorPanel;
+					Align := alClient;
+					OnEnter := EditorEnter;
+					OnExit := EditorExit;
+					OnKeyDown := EditorKeyDown;
+					OnChange := EditorChange;
+					OnSelectionChange := EditorChange;
+					PopupMenu := EditorPopup;
+				end;
+			Content := '; Assembly Source File'#13#10'; Created ' + DateToStr (Now) + ', ' + TimeToStr (Now) + #13#10;
+			if Assigned (TextEditor) then
+				TextEditor.ClearUndo;
+			Modified := False;
+			Invalidate;
+			SelectNode (TreeItem);
+			TreeItem.EditText;
+		end;
+	end;
+end;
+
+procedure TMainForm.FileNewQuillSourceFile(Sender: TObject);
+var
+	O: TQuillSourceFile;
+begin
+	if not Compiling then begin
+		if Assigned (SourceFiles.FindFileOfTypeInProject (TQuillSourceFile)) then
+			ShowDefaultMessageBox ('There may be only one Quill source file in each project.', 'Quill Error', mtProgramError)
+		else begin
+			O := TQuillSourceFile.Create (SourceFiles);
+			with O do begin
+				Folder := GetSelectedFolder (TQuillSourceFile);
+				FileName := GetNewFileName (FolderPath, '.qll');
+				OnError := AddError;
+				TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], O);
+				with TreeItem do begin
+					ImageIndex    := ClassImageIndex;
+					SelectedIndex := ImageIndex;
+				end;
+				ErrorList := Self.ErrorList;
+				if Assigned (TextEditor) then
+					with TextEditor do begin
+						Hide;
+						Parent := EditorPanel;
+						Align := alClient;
+						OnEnter := EditorEnter;
+						OnExit := EditorExit;
+						OnKeyDown := EditorKeyDown;
+						OnChange := EditorChange;
+						OnSelectionChange := EditorChange;
+						PopupMenu := EditorPopup;
+					end;
+				if FileExists (WithBackslash (TIGCCFolder) + QuillIncludeLocation + 'Template.qll') then
+					LoadFromFile (WithBackslash (TIGCCFolder) + QuillIncludeLocation + 'Template.qll')
+				else if FileExists (WithBackslash (TIGCCFolder) + CIncludeLocation + 'Template.qll') then
+					LoadFromFile (WithBackslash (TIGCCFolder) + CIncludeLocation + 'Template.qll')
+				else if FileExists (WithBackslash (TIGCCFolder) + GCCLocation + 'Template.qll') then
+					LoadFromFile (WithBackslash (TIGCCFolder) + GCCLocation + 'Template.qll');
+				Content := '// Quill Source File'#13#10'// Created ' + DateToStr (Now) + '; ' + TimeToStr (Now) + #13#10#13#10 + Content;
+				if Assigned (TextEditor) then
+					TextEditor.ClearUndo;
+				Modified := False;
+				Invalidate;
+				SelectNode (TreeItem);
+				TreeItem.EditText;
+			end;
+		end;
+	end;
+end;
+
+procedure TMainForm.FileNewTextFile(Sender: TObject);
+var
+	O: TNormalTextSourceFile;
+begin
+	O := TNormalTextSourceFile.Create (SourceFiles);
+	with O do begin
+		Folder := GetSelectedFolder (TTextSourceFile);
+		FileName := GetNewFileName (FolderPath, '.txt');
+		OnError := AddError;
+		TreeItem := CreateFileNode (TopNode.Item [ClassTreeIndex], O);
+		with TreeItem do begin
+			ImageIndex    := ClassImageIndex;
+			SelectedIndex := ImageIndex;
+		end;
+		ErrorList := Self.ErrorList;
+		if Assigned (TextEditor) then
+			with TextEditor do begin
+				Hide;
+				Parent := EditorPanel;
+				Align := alClient;
+				OnEnter := EditorEnter;
+				OnExit := EditorExit;
+				OnKeyDown := EditorKeyDown;
+				OnChange := EditorChange;
+				OnSelectionChange := EditorChange;
+				PopupMenu := EditorPopup;
+			end;
+		if Assigned (TextEditor) then
+			TextEditor.ClearUndo;
+		Modified := False;
+		SelectNode (TreeItem);
+		TreeItem.EditText;
+	end;
+end;
+
+procedure TMainForm.TreeItemSaveAs(Sender: TObject);
+var
+	Node: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then begin
+		TSourceFile(Node.Data).SaveAs;
+		Modify;
+		UpdateStatusBar;
+	end;
+end;
+
+procedure TMainForm.BeginCompilation;
+var
+	I: Integer;
+begin
+	ClearErrors;
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			with Items [I] as TSourceFile do
+				if not InProject then begin
+					RecompileFiles;
+					Break;
+				end;
+	OperationCancelled := False;
+	OperationSuccessful := False;
+end;
+
+procedure TMainForm.EndCompilation;
+begin
+	CompStop;
+	Application.Restore;
+	UpdateErrorWindow;
+	ShowErrors;
+end;
+
+procedure TMainForm.HelpAbout(Sender: TObject);
+begin
+	with TAboutForm.Create (Self) do try
+		ShowModal;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.DisplayHint(Sender: TObject);
+begin
+	with StatusBar.Panels do begin
+		BeginUpdate;
+		with Items [0] do begin
+			if Application.Hint = '' then
+				Width := 0
+			else
+				Width := 1000000;
+			Text := Application.Hint;
+		end;
+		EndUpdate;
+	end;
+end;
+
+procedure TMainForm.ShowHideErrors(Sender: TObject);
+begin
+	with ActionProjectShowErrors do begin
+		if Checked then
+			HideErrors
+		else
+			ShowErrors;
+	end;
+end;
+
+procedure TMainForm.UpdateEditButtons;
+var
+	TextSel: Boolean;
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) then begin
+		TextSel := (Editor.SelLength > 0) and (ActiveControl = Editor);
+		ActionEditDelete.Enabled := TextSel;
+		ActionEditCut.Enabled := TextSel;
+		ActionEditCopy.Enabled := TextSel;
+		ActionEditUndo.Enabled := (ActiveControl = Editor) and Editor.CanUndo;
+		ActionEditRedo.Enabled := (ActiveControl = Editor) and Editor.CanRedo;
+	end;
+end;
+
+procedure TMainForm.RecompileFiles;
+var
+	I: Integer;
+begin
+	with SourceFiles do
+		for I := 0 to Count - 1 do
+			with Items [I] as TSourceFile do
+				if Items [I] is THeaderSourceFile then
+					Invalidated := False
+				else if Compilable then
+					Invalidate;
+end;
+
+procedure TMainForm.FindString(Sender: TObject; AllFiles: Boolean);
+var
+	P: Integer;
+	S,
+	T: string;
+	Valid: Boolean;
+	FPos: Integer;
+	Editor: TMemoComponent;
+	NewSelection: TTreeNode;
+	FirstFile: Boolean;
+begin
+	NewSelection := ProjectTree.Selected;
+	if not Assigned (NewSelection) then
+		NewSelection := TopNode;
+	Valid := False;
+	FirstFile := True;
+	repeat
+		if Assigned (NewSelection.Data) and (TObject (NewSelection.Data) is TSourceFile) then
+			if TSourceFile (NewSelection.Data) is TTextSourceFile then begin
+				Editor := TTextSourceFile(NewSelection.Data).TextEditor;
+				if Assigned (Editor) then begin
+					with Sender as TFindDialog do begin
+						if (frFindNext in Options) and FirstFile then
+							P := Editor.Selection.REnd
+						else
+							if frDown in Options then
+								P := 0
+							else
+								P := Length (Editor.Text);
+						repeat
+							if frDown in Options then
+								T := Copy (Editor.Text, P + 1, Length (Editor.Text))
+							else
+								T := Copy (Editor.Text, 1, P - 1);
+							if frMatchCase in Options then
+								S := FindText
+							else begin
+								S := UpperCase (FindText);
+								T := UpperCase (T);
+							end;
+							if frDown in Options then
+								FPos := Pos (S, T)
+							else
+								FPos := LastPos (S, T);
+							if FPos > 0 then begin
+								Valid := True;
+								if frWholeWord in Options then begin
+									if ((FPos > 1) and (T <> '') and (T [FPos - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'])) then
+										Valid := False;
+									if ((FPos + Length (S) < Length (T)) and (T <> '') and (T [FPos + Length (S)] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'])) then
+										Valid := False;
+								end;
+								if not (frDown in Options) then
+									P := 0;
+								if not Valid then
+									Inc (P, FPos);
+							end;
+						until Valid or (FPos <= 0);
+						if Valid then begin
+							SelectNode (NewSelection);
+							with Editor do begin
+								with Selection do begin
+									DoChanging;
+									RStart := P + FPos;
+									RLength := Length (S);
+									DoChange;
+									ScrollInView (2);
+								end;
+							end;
+						end;
+					end;
+				end;
+			end;
+		if AllFiles and (not Valid) then begin
+			if frDown in (Sender as TFindDialog).Options then begin
+				NewSelection := NewSelection.GetNext;
+				if not Assigned (NewSelection) then
+					NewSelection := TopNode;
+			end else begin
+				NewSelection := NewSelection.GetPrev;
+				if not Assigned (NewSelection) then begin
+					NewSelection := TopNode;
+					while NewSelection.Count > 0 do
+						NewSelection := NewSelection.Item [NewSelection.Count - 1];
+				end;
+			end;
+			FirstFile := False;
+		end;
+	until (not AllFiles) or Valid or (NewSelection = ProjectTree.Selected);
+	if not Valid then
+		Abort;
+end;
+
+procedure TMainForm.ReplaceDlgReplace(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) then
+		with Sender as TReplaceDialog do
+			if (frReplace in Options) or (frReplaceAll in Options) then
+				repeat
+					if UpperCase (Editor.Selection.Text) = UpperCase (FindText) then
+						Editor.Selection.Text := ReplaceText;
+					Options := Options + [frFindNext];
+					FindString (Sender, False);
+				until not (frReplaceAll in Options);
+end;
+
+procedure TMainForm.FindText(Sender: TObject);
+begin
+	try
+		if Assigned (CurrentEditor) then
+			if CurrentEditor.Selection.RLength > 0 then
+				FindDlg.FindText := CurrentEditor.Selection.Text;
+		FindDlg.Execute;
+	except end;
+end;
+
+procedure TMainForm.ReplaceText(Sender: TObject);
+begin
+	try
+		if Assigned (CurrentEditor) then
+			if CurrentEditor.Selection.RLength > 0 then begin
+				ReplaceDlg.FindText := CurrentEditor.Selection.Text;
+				ReplaceDlg.ReplaceText := ReplaceDlg.FindText;
+			end;
+		ReplaceDlg.Execute;
+	except end;
+end;
+
+procedure TMainForm.FindOpenFile(Sender: TObject);
+var
+	I: Integer;
+	S: string;
+	QuotesInLine: Boolean;
+	SelectedNode: TTreeNode;
+	SourceFile: TSourceFile;
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) then begin
+		QuotesInLine := Pos ('"', Editor.Lines [Editor.Selection.StartRowCol.Row - 1]) > 0;
+		S := '';
+		for I := Editor.Selection.RStart - 1 downto 1 do begin
+			if (not QuotesInLine) and (Editor.Text [I] = ' ') then
+				Break;
+			if Editor.Text [I] in [' ', 'A'..'Z', 'a'..'z', '0'..'9', '_', '-', '.', '\', ':'] then
+				S := Editor.Text [I] + S
+			else
+				Break;
+		end;
+		for I := Editor.Selection.RStart to Length (Editor.Text) do begin
+			if (not QuotesInLine) and (Editor.Text [I] = ' ') then
+				Break;
+			if Editor.Text [I] in [' ', 'A'..'Z', 'a'..'z', '0'..'9', '_', '-', '.', '\', ':'] then
+				S := S + Editor.Text [I]
+			else
+				Break;
+		end;
+		S := Trim (S);
+		if Length (S) > 0 then begin
+			SourceFile := SourceFiles.FindFileNameOnly (S);
+			if Assigned (SourceFile) then
+				SourceFile.Edit
+			else begin
+				SelectedNode := ProjectTree.Selected;
+				if Assigned (SelectedNode) and (TObject (SelectedNode.Data) is TSourceFile) then
+					SourceFile := TSourceFile (SelectedNode.Data);
+				if FileExists (ExpandFileName (S)) then
+					AddSourceFile (ExpandFileName (S), True)
+				else if Assigned (SourceFile) and (SourceFile is TGNUAsmSourceFile) and FileExists (WithBackslash (TIGCCFolder) + GASIncludeLocation + S) then
+					AddSourceFile (WithBackslash (TIGCCFolder) + GASIncludeLocation + S, True)
+				else if Assigned (SourceFile) and (SourceFile is TAsmSourceFile) and FileExists (WithBackslash (TIGCCFolder) + ASMIncludeLocation + S) then
+					AddSourceFile (WithBackslash (TIGCCFolder) + ASMIncludeLocation + S, True)
+				else if FileExists (WithBackslash (TIGCCFolder) + CIncludeLocation + S) then
+					AddSourceFile (WithBackslash (TIGCCFolder) + CIncludeLocation + S, True)
+				else
+					ShowDefaultMessageBox ('File ''' + S + ''' not found.', 'Search Failed', mtProgramError);
+			end;
+		end;
+	end;
+end;
+
+procedure TMainForm.FindDlgFind(Sender: TObject);
+begin
+	try
+		FindString (Sender, True);
+	except
+		ShowDefaultMessageBox ('Text ''' + (Sender as TFindDialog).FindText + ''' not found.', 'Search Failed', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.ActionsExecute(Action: TBasicAction;
+	var Handled: Boolean);
+begin
+	Application.ProcessMessages;
+	Handled := False;
+end;
+
+procedure TMainForm.ProjectTreeEnter(Sender: TObject);
+begin
+	ActionEditDelete.Enabled := Assigned (ProjectTree.Selected) and Assigned (ProjectTree.Selected.Data);
+end;
+
+procedure TMainForm.ProjectTreeExit(Sender: TObject);
+begin
+	ActionEditDelete.Enabled := False;
+end;
+
+procedure TMainForm.ProjectTreeChanging(Sender: TObject; Node: TTreeNode;
+	var AllowChange: Boolean);
+begin
+	if not NoHideEditor then begin
+		if Assigned (EditorToHide) then
+			EditorToHide.Hide;
+		if (not Closing) and Assigned (PreviousNode) and Assigned (PreviousNode.Data) and (TObject (PreviousNode.Data) is TSourceFile) then
+			EditorToHide := TSourceFile(PreviousNode.Data).Editor
+		else
+			EditorToHide := NoEditor;
+	end;
+end;
+
+procedure TMainForm.EditorChange(Sender: TObject);
+begin
+	if ActiveControl = Sender then
+		UpdateEditButtons;
+	UpdateStatusBar;
+end;
+
+procedure TMainForm.FilePrint(Sender: TObject);
+var
+	Node: TTreeNode;
+	Cp: Integer;
+begin
+	Node := ProjectTree.Selected;
+	if Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) and (Printer.Printers.Count > 0) then try
+		PrintDlg.PrintRange := prAllPages;
+		PrintDlg.MaxPage := TSourceFile(Node.Data).CountPages;
+		PrintDlg.ToPage := PrintDlg.MaxPage;
+		if Assigned (CurrentEditor) then begin
+			if CurrentEditor.Selection.RLength > 0 then
+				PrintDlg.Options := PrintDlg.Options + [poSelection]
+			else
+				PrintDlg.Options := PrintDlg.Options - [poSelection];
+		end;
+		if Assigned (Sender) then begin
+			if not PrintDlg.Execute then
+				Abort;
+			Cp := PrintDlg.Copies;
+			if Cp < 1 then
+				Cp := 1;
+		end else
+			Cp := 1;
+		TSourceFile(Node.Data).Print (Cp, PrintDlg.PrintRange, PrintDlg.FromPage, PrintDlg.ToPage);
+	except
+		Abort;
+	end;
+end;
+
+procedure TMainForm.FilePrintQuickly(Sender: TObject);
+begin
+	FilePrint (nil);
+end;
+
+procedure TMainForm.TreeItemRename(Sender: TObject);
+begin
+	if Assigned (ProjectTree.Selected) then
+		ProjectTree.Selected.EditText;
+end;
+
+procedure TMainForm.HelpContents(Sender: TObject);
+begin
+	try
+		DocFile.DisplayContentsTab;
+	except
+		ShowDefaultMessageBox ('Error opening documentation.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.HelpIndex(Sender: TObject);
+begin
+	try
+		DocFile.DisplayIndexTab;
+	except
+		ShowDefaultMessageBox ('Error opening documentation.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.HelpSearch(Sender: TObject);
+begin
+	try
+		DocFile.DisplaySearchTab;
+	except
+		ShowDefaultMessageBox ('Error opening documentation.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.SplitterMoved(Sender: TObject);
+begin
+	StatusBar.Panels[1].Width := ProjectTree.Width;
+	Update;
+end;
+
+procedure TMainForm.UpdateStatusBar;
+var
+	S: string;
+	I: Integer;
+	Total: Integer;
+	Cell: TTextCell;
+	Node,
+	ClassNode: TTreeNode;
+begin
+	with StatusBar.Panels do begin
+		Total := 0;
+		Node := TopNode;
+		while Assigned (Node) do begin
+			if Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then
+				Inc (Total);
+			Node := Node.GetNext;
+		end;
+		S := IntToStr (Total) + ' File';
+		if Total <> 1 then
+			S := S + 's';
+		S := S + ' Total';
+		if Assigned (ProjectTree.Selected) then begin
+			ClassNode := GetSourceTypeFolder (ProjectTree.Selected);
+			if Assigned (ClassNode) then begin
+				Total := 0;
+				Node := ClassNode;
+				while Assigned (Node) and (Node <> ClassNode.GetNextSibling) do begin
+					if Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then
+						Inc (Total);
+					Node := Node.GetNext;
+				end;
+				S := S + ', ' + IntToStr (Total) + ' in Category';
+			end;
+		end;
+		if Items[1].Text <> S then
+			Items[1].Text := S;
+		if Assigned (CurrentEditor) then begin
+			with CurrentEditor do begin
+				if Enabled then begin
+					if Selection.RLength > 0 then begin
+						I := Selection.RLength + Selection.StartRowCol.Row - Selection.EndRowCol.Row;
+						if Selection.EndRowCol.Col > LineLength [Selection.EndRowCol.Row] then
+							Dec (I);
+						S := IntToStr (I);
+						if Items[3].Text <> S then
+							Items[3].Text := S;
+						if Items[4].Text <> '' then
+							Items[4].Text := '';
+						if Items[3].Width <> 60 then
+							Items[3].Width := 60;
+						if Items[4].Width <> 0 then
+							Items[4].Width := 0;
+					end else begin
+						Cell := Selection.StartRowCol;
+						S := IntToStr (Cell.Row);
+						if Items[3].Text <> S then
+							Items[3].Text := S;
+						S := IntToStr (Cell.Col);
+						if Items[4].Text <> S then
+							Items[4].Text := S;
+						if Items[3].Width <> 30 then
+							Items[3].Width := 30;
+						if Items[4].Width <> 30 then
+							Items[4].Width := 30;
+					end;
+					I := TextLength - LineCount + 1;
+					S := IntToStr (I) + ' Character';
+					if I <> 1 then
+						S := S + 's';
+					if Items[11].Text <> S then
+						Items[11].Text := S;
+					if Items[10].Width <> 1 then
+						Items[10].Width := 1;
+					if Items[11].Width <> 93 then
+						Items[11].Width := 93;
+					if Items[12].Width <> 1 then
+						Items[12].Width := 1;
+				end;
+			end;
+		end else begin
+			if Items[3].Text <> '' then
+				Items[3].Text := '';
+			if Items[4].Text <> '' then
+				Items[4].Text := '';
+			if Items[11].Text <> '' then
+				Items[11].Text := '';
+			if Items[3].Width <> 0 then
+				Items[3].Width := 0;
+			if Items[4].Width <> 0 then
+				Items[4].Width := 0;
+			if Items[10].Width <> 0 then
+				Items[10].Width := 0;
+			if Items[11].Width <> 0 then
+				Items[11].Width := 0;
+			if Items[12].Width <> 0 then
+				Items[12].Width := 0;
+		end;
+		Node := ProjectTree.Selected;
+		S := '';
+		if Assigned (Node) then begin
+			if Assigned (Node.Data) and (TObject (Node.Data) is TSourceFile) then begin
+				with TSourceFile (Node.Data) do
+					if (ProjectFile = '') and (ExtractFilePath (FileName) = 'C:\') then
+						S := LogicalFileName
+					else
+						S := FileName;
+			end else
+				if Node = TopNode then
+					S := ProjectFile;
+		end;
+		if Items[13].Text <> S then
+			Items[13].Text := S;
+	end;
+	Update;
+end;
+
+procedure TMainForm.ProjectTreeMouseDown(Sender: TObject;
+	Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+begin
+	if Button = mbRight then
+		SelectNode (ProjectTree.GetNodeAt (X, Y));
+end;
+
+procedure TMainForm.SetModified(const Value: Boolean);
+begin
+	FModified := Value;
+	UpdateStatusBar;
+	if Value then
+		Invalidated := True;
+end;
+
+procedure TMainForm.ToolBarManagerBandMove(Sender: TObject;
+	Control: TControl; var ARect: TRect);
+begin
+	Update;
+end;
+
+procedure TMainForm.ProjectTreeDragOver(Sender, Source: TObject; X,
+	Y: Integer; State: TDragState; var Accept: Boolean);
+var
+	S,
+	D: TTreeNode;
+	SameType,
+	FolderDest: Boolean;
+begin
+	Accept := False;
+	with ProjectTree do begin
+		S := Selected;
+		if Assigned (S) and Assigned (S.Data) then begin
+			D := GetNodeAt (X, Y);
+			if Assigned (D) and (D <> TopNode) and (D <> S) and (D <> S.Parent) then begin
+				SameType := (GetSourceTypeFolder (S) = GetSourceTypeFolder (D));
+				FolderDest := (not Assigned (D.Data)) or (TObject (D.Data) is TFolder);
+				if TObject (S.Data) is TSourceFile then
+					Accept := SameType or FolderDest
+				else
+					Accept := SameType and FolderDest;
+			end;
+		end;
+	end;
+end;
+
+procedure TMainForm.ProjectTreeDragDrop(Sender, Source: TObject; X,
+	Y: Integer);
+var
+	S,
+	D: TTreeNode;
+	FN: string;
+	F: TSourceFile;
+	Folder: TFolder;
+begin
+	with ProjectTree do begin
+		S := Selected;
+		if Assigned (S) and Assigned (S.Data) then begin
+			D := GetNodeAt (X, Y);
+			if Assigned (D) and (D <> TopNode) then begin
+				// Handle moving within one type.
+				if GetSourceTypeFolder (S) = GetSourceTypeFolder (D) then begin
+					// Handle moving to a different folder.
+					if (not Assigned (D.Data)) or (TObject (D.Data) is TFolder) then begin
+						S.MoveTo (D, naAddChild);
+						if TObject (S.Data) is TSourceFile then
+							with TSourceFile (S.Data) do begin
+								Folder := D.Data;
+								Invalidate;
+							end;
+					// Handle moving within one folder.
+					end else begin
+						if (S <> D) and (S.Parent = D.Parent) then begin
+							if D.Index > S.Index then begin
+								if D.GetNextSibling <> nil then
+									S.MoveTo (D.GetNextSibling, naInsert)
+								else
+									S.MoveTo (D, naAdd);
+							end else
+								S.MoveTo (D, naInsert);
+						end;
+					end;
+					Modify;
+				// Handle moving to a different type.
+				end else begin
+					if S.Parent <> D then begin
+						if TObject (S.Data) is TSourceFile then begin
+							with TSourceFile (S.Data) do begin
+								if FileExists (FileName) then
+									WarnIfModified
+								else
+                  Save;
+								FN := FileName;
+							end;
+							S.Delete;
+							Folder := nil;
+							if Assigned (D.Data) and (TObject (D.Data) is TFolder) then
+								Folder := D.Data;
+							D := GetSourceTypeFolder (D);
+							if Assigned (D) then begin
+								F := AddSourceFile (FN, False, TSourceFile.GetAppropriateClassFromTreeIndex (D.Index), Folder);
+								if Assigned (F) and Assigned (F.TreeItem) then
+									SelectNode (F.TreeItem);
+							end;
+							RecompileFiles;
+							Modify;
+						end;
+					end;
+				end;
+			end;
+			if Assigned (CurrentEditor) then
+				CurrentEditor.Refresh;
+			SortFiles;
+		end;
+	end;
+end;
+
+procedure TMainForm.ErrorListClick(Sender: TObject);
+begin
+	if Enabled and Assigned (ErrorList.Selected) and (ErrorList.SelCount = 1) then
+		TFoundError(ErrorList.Selected.Data).GoToPosition;
+end;
+
+function TMainForm.GetCurrentEditor: TMemoComponent;
+var
+	Node: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TTextSourceFile) then
+		Result := TTextSourceFile(Node.Data).TextEditor
+	else
+		Result := nil;
+end;
+
+procedure TMainForm.DeleteError(Sender: TObject);
+var
+	I: Integer;
+begin
+	if DeleteErrors then begin
+		with ErrorList.Items do
+			for I := Count - 1 downto 0 do
+				if Assigned (Item[I].Data) then
+					with TFoundError (Item[I].Data) do
+						if Range = Sender then
+							Item[I].Delete;
+		UpdateErrorWindow;
+	end;
+end;
+
+procedure TMainForm.UpdateFuncs;
+var
+	Node: TTreeNode;
+begin
+	Node := ProjectTree.Selected;
+	if Assigned (Node) and Assigned (Node.Data) and (TObject (Node.Data) is TSourceTextSourceFile) then
+		with TSourceTextSourceFile (Node.Data) do
+			Funcs := GetFunctions
+	else
+		SetLength (Funcs, 0);
+end;
+
+procedure TMainForm.FunctionPopupPopup(Sender: TObject);
+var
+	I,
+	P: Integer;
+	M: TMenuItem;
+begin
+	with (Sender as TPopupMenu).Items do begin
+		for I := Count - 1 downto 0 do
+			Remove (Items [I]);
+		UpdateFuncs;
+		for I := Low (Funcs) to High (Funcs) do begin
+			M := TMenuItem.Create (Self);
+			with M do begin
+				Tag := I;
+				Caption := Funcs[I].Name;
+				OnClick := FindFunctionFromPopup;
+			end;
+			P := Pos ('main', Funcs[I].Name);
+			if (P <> 0) and (P = Length (Funcs[I].Name) - Length ('main') + 1) then
+				Insert (0, M)
+			else
+				Add (M);
+		end;
+		if Count <= 0 then
+			Add (NoFunctionsItem);
+	end;
+end;
+
+procedure TMainForm.FindFunctions(Sender: TObject);
+var
+	I: Integer;
+	Editor: TMemoComponent;
+begin
+	UpdateFuncs;
+	with TFunctionsForm.Create (Self) do try
+		Funcs := @Self.Funcs;
+		with FuncList.Items do begin
+			BeginUpdate;
+			Clear;
+			for I := Low (Self.Funcs) to High (Self.Funcs) do
+				AddObject (Self.Funcs[I].Name, TObject (I));
+			EndUpdate;
+		end;
+		FuncListClick (FuncList);
+		case ShowModal of
+			mrYes: begin
+				Editor := CurrentEditor;
+				if Assigned (Editor) then begin
+					Editor.Selection.NoSelAtPos (Editor.CellToCharIdx (TextCell (Self.Funcs[Integer(FuncList.Items.Objects[FuncList.ItemIndex])].PrototypeLine, 1)));
+					Editor.Selection.ScrollInView (5);
+				end;
+			end;
+			mrNo: begin
+				Editor := CurrentEditor;
+				if Assigned (Editor) then begin
+					Editor.Selection.NoSelAtPos (Editor.CellToCharIdx (TextCell (Self.Funcs[Integer(FuncList.Items.Objects[FuncList.ItemIndex])].ImplementationLine, 1)));
+					Editor.Selection.ScrollInView (5);
+				end;
+			end;
+		end;
+		with FuncList.Items do begin
+			BeginUpdate;
+			for I := Count - 1 downto 0 do begin
+				Objects [I] := nil;
+				Delete (I);
+			end;
+			EndUpdate;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.FindFunctionFromPopup(Sender: TObject);
+var
+	L: Integer;
+	Editor: TMemoComponent;
+begin
+	if Sender is TMenuItem then
+		with Sender as TMenuItem do begin
+			if Funcs[Tag].ImplementationLine > 0 then
+				L := Funcs[Tag].ImplementationLine
+			else
+				L := Funcs[Tag].PrototypeLine;
+			if L > 0 then begin
+				Editor := CurrentEditor;
+				if Assigned (Editor) then begin
+					Editor.Selection.NoSelAtPos (Editor.CellToCharIdx (TextCell (L, 1)));
+					Editor.Selection.ScrollInView (5);
+					if Editor.Visible and Editor.Enabled then
+						ActiveControl := Editor;
+				end;
+			end;
+		end;
+end;
+
+procedure TMainForm.IncreaseIndent(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) then
+		Editor.ChangeIndent (1);
+end;
+
+procedure TMainForm.DecreaseIndent(Sender: TObject);
+var
+	Editor: TMemoComponent;
+begin
+	Editor := CurrentEditor;
+	if Assigned (Editor) then
+		Editor.ChangeIndent (-1);
+end;
+
+procedure TMainForm.SortFiles;
+var
+	CurFileIndex: Integer;
+procedure DoSortFiles(Node: TTreeNode);
+var
+	I: Integer;
+begin
+	with Node do begin
+		if Assigned (Data) and (TObject (Data) is TSourceFile) then begin
+			with TSourceFile (Data) do
+				if Index > CurFileIndex then
+					Index := CurFileIndex;
+			Inc (CurFileIndex);
+		end;
+		for I := 0 to Count - 1 do
+			DoSortFiles (Item [I]);
+	end;
+end;
+var
+	I: Integer;
+begin
+	CurFileIndex := 0;
+	{	This is supposed to be: DoSortFiles (TopNode);
+		However, header files are dependent on the other
+		files and therefore have to be put after all the
+		others. }
+	with TopNode do begin
+		for I := 0 to Count - 1 do
+			if I <> THeaderSourceFile.GetClassTreeIndex then
+				DoSortFiles (Item [I]);
+		if Count > THeaderSourceFile.GetClassTreeIndex then
+			DoSortFiles (Item [THeaderSourceFile.GetClassTreeIndex]);
+	end;
+end;
+
+procedure TMainForm.AppCompSetMessage(const Msg: string);
+begin
+	with StatusBar do
+		Panels.Items[6].Text := Msg + '...';
+	if not Compiling then begin
+		Compiling := True;
+		CompUpdate;
+		UpdateDebugSettings;
+		with StatusBar.Panels do begin
+			Items[5].Width := 5;
+			Items[6].Width := 180;
+			Items[7].Width := 100;
+			Items[8].Width := 100;
+			Items[9].Width := 1000000;
+		end;
+	end;
+end;
+
+procedure TMainForm.AppCompStartFile;
+var
+	I: Integer;
+begin
+	Application.Hint := '';
+	CompFinishAndStop := False;
+	CompStopNow := False;
+	CompFileStartTime := Now;
+	CompLastTime := 0;
+	if not Compiling then begin
+		CompStartTime := CompFileStartTime;
+		ToolBarNewButton.Enabled := False;
+		MenuFileNew.Enabled := False;
+		ActionFileOpen.Enabled := False;
+		ActionFileExit.Enabled := False;
+		ActionProjectAddFiles.Enabled := False;
+		ActionProjectCompile.Visible := False;
+		ActionProjectMake.Visible := False;
+		ActionProjectBuild.Visible := False;
+		ActionProjectStopCompilation.Enabled := True;
+		ActionProjectForceQuitCompiler.Enabled := True;
+		ActionProjectStopCompilation.Visible := True;
+		ActionProjectForceQuitCompiler.Visible := True;
+		with RecentFiles do
+			for I := 0 to Count - 1 do
+				with TRecentFileMenuItem (Objects [I]) do begin
+					FileMenuItem.Enabled := False;
+					PopupMenuItem.Enabled := False;
+				end;
+	end;
+end;
+
+procedure TMainForm.AppCompStop;
+var
+	I: Integer;
+begin
+	if Compiling then begin
+		Compiling := False;
+		ActionProjectStopCompilation.Visible := False;
+		ActionProjectForceQuitCompiler.Visible := False;
+		ToolBarNewButton.Enabled := True;
+		MenuFileNew.Enabled := True;
+		ActionFileOpen.Enabled := True;
+		ActionFileExit.Enabled := True;
+		ActionProjectAddFiles.Enabled := True;
+		ActionProjectCompile.Visible := True;
+		ActionProjectMake.Visible := True;
+		ActionProjectBuild.Visible := True;
+		with RecentFiles do
+			for I := 0 to Count - 1 do
+				with TRecentFileMenuItem (Objects [I]) do begin
+					FileMenuItem.Enabled := True;
+					PopupMenuItem.Enabled := True;
+				end;
+		UpdateDebugSettings;
+		with StatusBar.Panels do begin
+			Items[5].Width := 0;
+			Items[6].Width := 0;
+			Items[7].Width := 0;
+			Items[8].Width := 0;
+			Items[9].Width := 0;
+		end;
+	end;
+end;
+
+procedure TMainForm.AppCompUpdate;
+const
+	SecondsPerDay = 24 * 60 * 60;
+function CustomTimeToStr(ConvTime: TDateTime): string;
+var
+	Seconds: Integer;
+	MinStr,
+	SecStr: string;
+begin
+	Seconds := Trunc (ConvTime * SecondsPerDay);
+	MinStr := IntToStr (Seconds div 60);
+	SecStr := IntToStr (Seconds mod 60);
+	while Length (SecStr) < 2 do
+		SecStr := '0' + SecStr;
+	Result := MinStr + ':' + SecStr;
+end;
+var
+	CurTime: TDateTime;
+begin
+	CurTime := Now;
+	if Trunc (CompLastTime * SecondsPerDay) <> Trunc (CurTime * SecondsPerDay) then begin
+		CompLastTime := CurTime;
+		with StatusBar, Panels do begin
+			Items[7].Text := 'File Time: ' + CustomTimeToStr (CurTime - CompFileStartTime);
+			Items[8].Text := 'Total Time: ' + CustomTimeToStr (CurTime - CompStartTime);
+			Update;
+		end;
+	end;
+end;
+
+procedure TMainForm.DisplayFolderMessage;
+var
+	S: string;
+begin
+	if OperationSuccessful and (not OperationCancelled) and OpenFolderMessage then begin
+		if ProjectTarget = ptArchive then
+			S := 'The project has been compiled successfully.'#13#10#13#10'Archive Size: ' + IntToStr (ProgSize) + ' Bytes'#13#10#13#10'Do you want to open the project folder?'
+		else
+			with OptimizeInfo do begin
+				S := 'The project has been compiled successfully.'#13#10#13#10'Program Variable Size: ' + IntToStr (ProgramSize) + ' Bytes'#13#10;
+				if DataSize > 0 then
+					S := S + 'Data Variable Size: ' + IntToStr (DataSize) + ' Bytes'#13#10;
+				if BSSSize > 0 then
+					S := S + 'BSS Size: ' + IntToStr (BSSSize) + ' Bytes'#13#10;
+				S := S + 'Absolute Relocs: ' + IntToStr (RelocCount) + #13#10'Natively Emitted Relocs: ' + IntToStr (NativeRelocCount) + #13#10;
+				if OptimizeBranchesResult > 0 then begin
+					if OptimizeBranches then
+						S := S + 'Relocs Saved'
+					else
+						S := S + 'Relocs Savable';
+					S := S + ' by Branch Optimization: ' + IntToStr (OptimizeBranchesResult) + #13#10;
+				end;
+				if OptimizeMovesResult > 0 then begin
+					if OptimizeMoves then
+						S := S + 'Relocs Saved'
+					else
+						S := S + 'Relocs Savable';
+					S := S + ' by Move Optimization: ' + IntToStr (OptimizeMovesResult) + #13#10;
+				end;
+				if OptimizeTestsResult > 0 then begin
+					if OptimizeTests then
+						S := S + 'Relocs Saved'
+					else
+						S := S + 'Relocs Savable';
+					S := S + ' by Test Optimization: ' + IntToStr (OptimizeTestsResult) + #13#10;
+				end;
+				if OptimizeCalcsResult > 0 then begin
+					if OptimizeCalcs then
+						S := S + 'Relocs Saved'
+					else
+						S := S + 'Relocs Savable';
+					S := S + ' by Calculation Optimization: ' + IntToStr (OptimizeCalcsResult) + #13#10;
+				end;
+				if UseFLineJumpsResult > 0 then begin
+					if UseFLineJumps or Use4ByteFLineJumps then
+						S := S + 'Relocs Saved'
+					else
+						S := S + 'Relocs Savable';
+					S := S + ' by F-Line Jumps: ' + IntToStr (UseFLineJumpsResult) + #13#10;
+				end;
+				if CutRangesResult > 0 then begin
+					if CutRanges then
+						S := S + 'Space Saved'
+					else
+						S := S + 'Space Savable';
+					S := S + ' by Range-Cutting: ' + IntToStr (CutRangesResult) + ' Bytes'#13#10;
+				end;
+				if NearAssemblyResult > 0 then
+					S := S + 'Space Savable by Using GNU Assembler ''-l'' Switch: ' + IntToStr (NearAssemblyResult) + ' Bytes'#13#10;
+				S := S + #13#10'Do you want to open the project folder?';
+			end;
+		if ShowDefaultMessageBox (S, 'Compilation Successful', mtQuestion) = idYes then
+			ShellExecute (0, nil, PChar (ExtractFilePath (ProjectFile)), nil, nil, sw_ShowNormal);
+	end;
+end;
+
+procedure TMainForm.ProjectStopCompilation(Sender: TObject);
+begin
+	CompFinishAndStop := True;
+	ActionProjectStopCompilation.Enabled := False;
+end;
+
+procedure TMainForm.ProjectForceQuitCompiler(Sender: TObject);
+begin
+	CompStopNow := True;
+end;
+
+procedure TMainForm.WMDropFiles(var Msg: TMessage);
+var
+	DropHandle: THandle;
+	I,
+	FileCount: Integer;
+	CurFile: array [0..512] of Char;
+begin
+	DropHandle := Msg.WParam;
+	FileCount := DragQueryFile (DropHandle, High (Cardinal), nil, 0);
+	for I := 0 to FileCount - 1 do begin
+		DragQueryFile (DropHandle, I, CurFile, SizeOf (CurFile) - 1);
+		if LowerCase (ExtractFileExt (AnsiString (CurFile))) = LowerCase (ProjectFileExt) then
+			FileOpen (AnsiString (CurFile))
+		else
+			AddSourceFile (AnsiString (CurFile), True);
+	end;
+	DragFinish (DropHandle);
+end;
+
+procedure TMainForm.HelpNews(Sender: TObject);
+begin
+	with TNewsForm.Create (Self) do try
+		Execute;
+	finally
+		Free;
+	end;
+end;
+
+function TMainForm.GetVTIWindow: HWnd;
+begin
+	CurVTIType := cvNone;
+	Result := FindWindow ('TEmuWnd', 'Virtual TI-89');
+	if Result = 0 then begin
+		Result := FindWindow ('TEmuWnd', 'Virtual TI-92+');
+		if Result = 0 then begin
+			Result := FindWindow ('TEmuWnd', 'Virtual TI-92');
+			if Result <> 0 then
+				CurVTIType := cvTI92;
+		end else
+			CurVTIType := cvTI92Plus;
+	end else
+		CurVTIType := cvTI89;
+	if Result = 0 then begin
+		if Length (VTIPath) > 0 then begin
+			with TVTIStartForm.Create (Self) do try
+				if ShowModal = mrOK then begin
+					Result := VTIWindow;
+					CurVTIType := VTIType;
+				end else
+					Abort;
+			finally
+				Free;
+			end;
+		end else begin
+			ShowDefaultMessageBox ('Virtual TI is not running.', 'Error', mtProgramError);
+			Abort;
+		end;
+	end;
+end;
+
+procedure TMainForm.SendFiles(FNList: array of string);
+var
+	Win: HWnd;
+procedure SendKey(Key: Byte);
+begin
+	PostMessage (Win, WM_KEYDOWN, Key, 0);
+	PostMessage (Win, WM_KEYUP, Key, 0);
+end;
+var
+	I: Integer;
+	EditWin,
+	ButtonWin: HWnd;
+	StartTime: Cardinal;
+	FileString: string;
+	Name: array [0..32] of Char;
+	Connection: TLinkConnection;
+	Size: Word;
+	Total: Cardinal;
+	Progress: DWord;
+	ProgressForm: TSendProgressForm;
+begin
+	OperationSuccessful := False;
+	OperationCancelled := False;
+	if Length (FNList) > 0 then begin
+		if TransferTarget = ttVTI then begin
+			Win := GetVTIWindow;
+			GetWindowThreadProcessID (Win, @ProcID);
+			SendKey (VK_SCROLL);
+			SendKey (VK_ESCAPE);
+			if CurVTIType = cvTI89 then
+				SendKey (VK_HOME);
+			SendKey (VK_F10);
+			StartTime := GetTickCount;
+			SendWin := 0;
+			repeat
+				EnumWindows (@EnumWindowsFunc, 0);
+			until (SendWin <> 0) or (GetTickCount - StartTime >= 10000);
+			if SendWin = 0 then begin
+				ShowDefaultMessageBox ('Error displaying send dialog.', 'Error', mtProgramError);
+				Abort;
+			end else begin
+				SetForegroundWindow (SendWin);
+				repeat
+					EditWin := GetWindow (SendWin, GW_CHILD);
+					GetClassName (EditWin, Name, 32);
+					while (EditWin <> 0) and (UpperCase (AnsiString (Name)) <> 'EDIT') do begin
+						EditWin := GetWindow (EditWin, GW_HWNDNEXT);
+						if EditWin <> 0 then
+							GetClassName (EditWin, Name, 32);
+					end;
+					if EditWin <> 0 then begin
+						StartTime := GetTickCount;
+						while (SendMessage (EditWin, WM_GETTEXTLENGTH, 0, 0) <= 0) and (GetTickCount - StartTime < 5000) do;
+						FileString := '';
+						for I := Low (FNList) to High (FNList) do begin
+							if CurVTIType = cvTI92Plus then
+								FNList [I] := StringReplace (FNList [I], '.89', '.9x', []);
+							if not FileExists (FNList [I]) then begin
+								ShowDefaultMessageBox ('The file "' + FNList [I] + '" could not be found.', 'Error', mtProgramError);
+								Abort;
+							end;
+							Insert ('"' + FNList [I] + '" ', FileString, Length (FileString) + 1);
+						end;
+						Delete (FileString, Length (FileString), 1);
+						SendMessage (EditWin, WM_SETTEXT, 0, Integer (PChar (FileString)));
+					end;
+					ButtonWin := GetWindow (SendWin, GW_CHILD);
+					GetClassName (ButtonWin, Name, 32);
+					while (ButtonWin <> 0) and ((UpperCase (AnsiString (Name)) <> 'BUTTON') or ((GetWindowLong (ButtonWin, GWL_STYLE) and BS_DEFPUSHBUTTON) = 0) or ((GetWindowLong (ButtonWin, GWL_STYLE) and BS_CHECKBOX) <> 0)) do begin
+						ButtonWin := GetWindow (ButtonWin, GW_HWNDNEXT);
+						if ButtonWin <> 0 then
+							GetClassName (ButtonWin, Name, 32);
+					end;
+				until SendMessage (EditWin, WM_GETTEXTLENGTH, 0, 0) >= Length (FNList [Low (FNList)]);
+				if ButtonWin <> 0 then begin
+					SendMessage (ButtonWin, WM_LBUTTONDOWN, 0, 0);
+					SendMessage (ButtonWin, WM_LBUTTONUP, 0, 0);
+				end;
+			end;
+			ShowWindow (Win, SW_SHOWNORMAL);
+			SetForegroundWindow (Win);
+		end else if TransferTarget = ttCalc then begin
+			FillChar (Connection, SizeOf (Connection), 0);
+			Connection.Port := LinkPort;
+			Connection.CableType := LinkCable;
+			if CreateConnection (Connection) then try
+				if OpenConnection (Connection) and GetCalcType (Connection) then begin
+					Total := 0;
+					for I := Low (FNList) to High (FNList) do begin
+						case Connection.CalcType of
+							cdTI92Plus:
+								FNList [I] := StringReplace (FNList [I], '.89', '.9x', []);
+							cdV200:
+								FNList [I] := StringReplace (FNList [I], '.89', '.v2', []);
+							cdTI92:
+								FNList [I] := StringReplace (FNList [I], '.89', '.92', []);
+						end;
+						if not FileExists (FNList [I]) then begin
+							ShowDefaultMessageBox ('The file "' + FNList [I] + '" could not be found.', 'Error', mtProgramError);
+							Abort;
+						end;
+						if not CheckFileFormat (Connection, PChar (FNList [I]), nil, nil, @Size) then begin
+							ShowDefaultMessageBox ('Error sending file.', 'Error', mtProgramError);
+							Abort;
+						end;
+						Inc (Total, Size);
+					end;
+					Enabled := False;
+					try
+						ProgressForm := TSendProgressForm.Create (Self);
+						with ProgressForm do try
+							ProgressBar.Max := Total;
+							Show;
+							Update;
+							Progress := 0;
+							for I := Low (FNList) to High (FNList) do begin
+								FileNameLabel.Caption := ExtractFileName (FNList [I]);
+								if not SendFile (Connection, nil, nil, PChar (FNList [I]), @Progress, ProgressProg, ProgressForm) then begin
+									if Cancelled then
+										OperationCancelled := True
+									else
+										ShowDefaultMessageBox ('Error sending file. Please check whether your calculator is on the home screen.', 'Error', mtProgramError);
+									Abort;
+								end;
+							end;
+						finally
+							CloseNow := True;
+							Free;
+						end;
+					finally
+						Enabled := True;
+					end;
+				end else begin
+					ShowDefaultMessageBox ('Error linking to calculator.', 'Error', mtProgramError);
+					Abort;
+				end;
+			finally
+				CloseConnection (Connection);
+			end else begin
+				ShowDefaultMessageBox ('Error opening link port.', 'Error', mtProgramError);
+				Abort;
+			end;
+		end;
+		OperationSuccessful := True;
+	end;
+end;
+
+procedure TMainForm.ExecuteCommandLine(const Line: string);
+var
+	Win: HWnd;
+procedure SendKey(Key: Byte);
+begin
+	SendMessage (Win, WM_KEYDOWN, Key, 0);
+	SendMessage (Win, WM_KEYUP, Key, 0);
+	Sleep (20);
+end;
+var
+	I: Integer;
+	Connection: TLinkConnection;
+begin
+	if TransferTarget = ttVTI then begin
+		Win := GetVTIWindow;
+		SendKey (VK_SCROLL);
+		SendKey (VK_ESCAPE);
+		SendKey (VK_ESCAPE);
+		if CurVTIType = cvTI89 then
+			SendKey (VK_HOME);
+		SendKey (VK_DELETE);
+		SendKey (VK_DELETE);
+		for I := 1 to Length (Line) do
+			if Line [I] in ['A'..'Z', 'a'..'z', '0'..'9'] then
+				SendKey (Byte (UpCase (Line [I])))
+			else if Line [I] = '(' then
+				SendKey ($DB)
+			else if Line [I] = ')' then
+				SendKey ($DD)
+			else if Line [I] = ',' then
+				SendKey ($BC)
+			else if Line [I] = '.' then
+				SendKey (VK_DECIMAL)
+			else if Line [I] = '+' then
+				SendKey (VK_ADD)
+			else if Line [I] = '-' then
+				SendKey (VK_SUBTRACT)
+			else if Line [I] = '*' then
+				SendKey (VK_MULTIPLY)
+			else if Line [I] = '/' then
+				SendKey (VK_DIVIDE)
+			else if Line [I] = '\' then begin
+				SendKey (VK_MENU);
+				SendKey (Byte ('2'));
+			end;
+		SendKey (VK_RETURN);
+	end else if TransferTarget = ttCalc then begin
+		FillChar (Connection, SizeOf (Connection), 0);
+		Connection.Port := LinkPort;
+		Connection.CableType := LinkCable;
+		if CreateConnection (Connection) then try
+			if OpenConnection (Connection) then
+				ExecuteHomeLine (Connection, Line)
+			else begin
+				ShowDefaultMessageBox ('Error linking to calculator.', 'Error', mtProgramError);
+				Abort;
+			end;
+		finally
+			CloseConnection (Connection);
+		end else begin
+			ShowDefaultMessageBox ('Error opening link port.', 'Error', mtProgramError);
+			Abort;
+		end;
+	end;
+end;
+
+procedure TMainForm.DebugRun(Sender: TObject);
+var
+	Files: array of string;
+begin
+	OperationSuccessful := True;
+	OperationCancelled := False;
+	if Invalidated then
+		MakeFileWrapped;
+	if OperationSuccessful and (not OperationCancelled) and (FileExists (ChangeFileExt (ProjectFile, '.89z')) or FileExists (ChangeFileExt (ProjectFile, '.9xz')) or FileExists (ChangeFileExt (ProjectFile, '.v2z')) or FileExists (ChangeFileExt (ProjectFile, '.92p'))) then begin
+		if Runnable then begin
+			SetLength (Files, 0);
+			case ProjectTarget of
+				ptRegular: begin
+					SetLength (Files, 1);
+					Files [High (Files)] := ChangeFileExt (ProjectFile, '.89z');
+					if Pack and (ssPack in SpecialSupport) then begin
+						SetLength (Files, Length (Files) + 1);
+						Files [High (Files)] := ChangeFileExt (ProjectFile, '.89y');
+					end;
+					if UseDataVar then begin
+						SetLength (Files, Length (Files) + 1);
+						Files [High (Files)] := ChangeFileExt (ProjectFile, '-data.89y');
+					end;
+				end;
+				ptFargo: begin
+					SetLength (Files, 1);
+					Files [High (Files)] := ChangeFileExt (ProjectFile, '.92p');
+				end;
+			end;
+			if Length (Files) > 0 then begin
+				SendFiles (Files);
+				if OperationSuccessful then
+					ExecuteCommandLine (TopNode.Text + '(' + CommandLine + ')');
+			end;
+		end else
+			DisplayFolderMessage;
+	end;
+end;
+
+procedure TMainForm.DebugPause(Sender: TObject);
+var
+	Win: HWnd;
+procedure SendKey(Key: Byte);
+begin
+	PostMessage (Win, WM_KEYDOWN, Key, 0);
+	PostMessage (Win, WM_KEYUP, Key, 0);
+end;
+begin
+	Win := GetVTIWindow;
+	SendKey (VK_F11);
+	ShowWindow (Win, SW_SHOWNORMAL);
+	SetForegroundWindow (Win);
+end;
+
+procedure TMainForm.DebugReset(Sender: TObject);
+var
+	Win: HWnd;
+procedure SendKey(Key: Byte);
+begin
+	PostMessage (Win, WM_KEYDOWN, Key, 0);
+	PostMessage (Win, WM_KEYUP, Key, 0);
+end;
+begin
+	Win := GetVTIWindow;
+	SendKey (VK_APPS);
+	SendKey (Byte ('T'));
+	ShowWindow (Win, SW_SHOWNORMAL);
+	SetForegroundWindow (Win);
+end;
+
+function TMainForm.GetInvalidated: Boolean;
+var
+	I: Integer;
+begin
+	Result := FInvalidated;
+	if not Result then
+		with SourceFiles do
+			for I := 0 to Count - 1 do
+				with Items [I] as TSourceFile do
+					if (Compilable or (Items [I] is THeaderSourceFile)) and Invalidated then begin
+						Result := True;
+						Break;
+					end;
+end;
+
+procedure TMainForm.UpdateDebugSettings;
+var
+	CanRun: Boolean;
+begin
+	CanRun := Runnable;
+	ActionDebugRun.Enabled := not Compiling;
+	ActionDebugPause.Enabled := (not Compiling) and (TransferTarget = ttVTI);
+	ActionDebugReset.Enabled := (not Compiling) and (TransferTarget = ttVTI);
+	MainMenuDebug.Visible := CanRun;
+	if not CanRun then
+		ToolBarDebugLine.Parent := nil;
+	ToolBarRunButton.Visible := CanRun;
+	ToolBarPauseButton.Visible := CanRun;
+	ToolBarDebugLine.Visible := CanRun;
+	if CanRun then begin
+		ToolBarDebugLine.Parent := MainToolBar;
+		ToolBarDebugLine.Left := ToolBarPauseButton.Left + ToolBarPauseButton.Width;
+	end;
+end;
+
+procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
+	Shift: TShiftState);
+var
+	NewSelection: TTreeNode;
+begin
+	if (Key = vk_F9) and (Shift = [ssShift, ssCtrl, ssAlt]) then begin
+		if TransferTarget = ttVTI then
+			TransferTarget := ttCalc
+		else
+			TransferTarget := ttVTI;
+		SavePreferences;
+		UpdateDebugSettings;
+	end else if (Key = vk_Tab) and (Shift = [ssCtrl]) then begin
+		NewSelection := ProjectTree.Selected;
+		if Assigned (NewSelection) then begin
+			repeat
+				NewSelection := NewSelection.GetNext;
+				if not Assigned (NewSelection) then
+					NewSelection := TopNode;
+			until (NewSelection.IsVisible and Assigned (NewSelection.Data)) or (NewSelection = ProjectTree.Selected);
+			if Assigned (NewSelection.Data) then
+				SelectNode (NewSelection);
+			if Assigned (CurrentEditor) and CurrentEditor.Enabled then try
+				CurrentEditor.SetFocus;
+			except end;
+		end;
+	end;
+end;
+
+procedure TMainForm.SelectNode(Node: TTreeNode);
+var
+	Allow: Boolean;
+begin
+	if PreviousNode <> Node then begin
+		Allow := True;
+		ProjectTreeChanging (ProjectTree, Node, Allow);
+		if Allow then begin
+			NoHideEditor := True;
+			ProjectTree.Selected := Node;
+			NoHideEditor := False;
+		end;
+	end;
+end;
+
+procedure TMainForm.ChangeNotificationTick(Sender: TObject);
+var
+	I: Integer;
+begin
+	if not InChangeNotification then begin
+		InChangeNotification := True;
+		with SourceFiles do
+			for I := 0 to Count - 1 do
+				with TSourceFile (Items [I]) do
+					TestChange;
+		InChangeNotification := False;
+	end;
+end;
+
+procedure TMainForm.ResetProjectSettings;
+begin
+	ProjectTarget         := ptRegular;
+	UseDataVar            := False;
+	DataVar               := '';
+	DataVarCopy           := True;
+	DataVarCopyIfArchived := True;
+	Pack                  := False;
+	PackVar               := '';
+	GCCSwitches           := '-Os -Wall -W -Wwrite-strings -ffunction-sections -fdata-sections';
+	AsSwitches            := '';
+	AsmSwitches           := '-g -t';
+	DebugInfo             := False;
+	StdLib                := True;
+	InitBSS               := True;
+	OptimizeNOPs          := True;
+	OptimizeReturns       := True;
+	OptimizeBranches      := True;
+	OptimizeMoves         := True;
+	OptimizeTests         := True;
+	OptimizeCalculations  := True;
+	RemoveUnusedSections  := True;
+	CutUnusedRanges       := True;
+	ReorderSections       := True;
+	MergeConstants        := True;
+	OutputBin             := False;
+	CommandLine           := '';
+	PostBuildProcessFile  := '';
+	if Assigned (PredefinedLibOptions) then
+		with PredefinedLibOptions do begin
+			CalcDests                := [cdTI89, cdTI92Plus, cdV200];
+			OptimizeCalcConsts       := False;
+			KernelFormat             := kfNone;
+			UseMinAMS                := True;
+			MinAMS                   := '1.00';
+			RelocFormat              := rfAMS;
+			ROMCallFormat            := rfDirect;
+			BSSRefFormat             := rfKernel;
+			DataRefFormat            := rfKernel;
+			UseFLineJumps            := False;
+			UseInternalFLineEmulator := False;
+			UseReturnValue           := False;
+			EnableErrorReturn        := False;
+			SaveScreen               := True;
+		end;
+end;
+
+procedure TMainForm.AddToRecent(const FileName: string);
+var
+	I: Integer;
+	O: TRecentFileMenuItem;
+begin
+	with RecentFiles do begin
+		for I := 0 to Count - 1 do
+			if (I >= MaxRecentFiles - 1) or (UpperCase (Strings [I]) = UpperCase (FileName)) then begin
+				if I = 0 then
+					Exit
+				else begin
+					Objects[I].Free;
+					Delete (I);
+					Break;
+				end;
+			end;
+		RecentFilesLine.Visible := True;
+		O := TRecentFileMenuItem.Create;
+		with O do begin
+			FileMenuItem := TMenuItem.Create (Self);
+			with FileMenuItem do begin
+				Caption := WithoutExt (ExtractFileName (FileName));
+				Hint := FileName;
+				OnClick := RecentFileClick;
+			end;
+			MainMenuFile.Insert (RecentFilesLine.MenuIndex + 1, FileMenuItem);
+			PopupMenuItem := TMenuItem.Create (Self);
+			with PopupMenuItem do begin
+				Caption := FileName;
+				Hint := FileName;
+				OnClick := RecentFileClick;
+			end;
+			RecentFilesPopup.Items.Insert (0, PopupMenuItem);
+		end;
+		InsertObject (0, FileName, O);
+	end;
+	UpdateRecent;
+end;
+
+procedure TMainForm.UpdateRecent;
+begin
+	RecentFilesLine.Visible := RecentFiles.Count > 0;
+	NoFilesItem.Visible := RecentFiles.Count <= 0;
+end;
+
+procedure TMainForm.RecentFileClick(Sender: TObject);
+var
+	I: Integer;
+	FileName: string;
+begin
+	FileName := (Sender as TMenuItem).Hint;
+	if FileExists (FileName) then
+		FileOpen (FileName)
+	else begin
+		with RecentFiles do
+			for I := 0 to Count - 1 do
+				if UpperCase (Strings [I]) = UpperCase (FileName) then begin
+					Objects[I].Free;
+					Delete (I);
+					Break;
+				end;
+		UpdateRecent;
+		ShowDefaultMessageBox ('File ''' + WithoutExt (ExtractFileName (FileName)) + ''' not found.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.ToolsConfigure(Sender: TObject);
+var
+	I: Integer;
+begin
+	with TToolsForm.Create (Self) do try
+		with Self.ToolsList do
+			for I := 0 to Count - 1 do
+				with ToolsList.Items.Add, TToolsListItem (Items [I]) do begin
+					Caption := Title;
+					SubItems.Add (CommandLine);
+					SubItems.Add (WorkingDir);
+					SubItems.Add (WindowStateToString (WindowState));
+				end;
+		if ShowModal = mrOK then begin
+			Self.ToolsList.Clear;
+			with ToolsList.Items do begin
+				ToolsLine.Visible := Count > 0;
+				for I := 0 to Count - 1 do
+					with Item [I] do
+						AddTool (Caption, SubItems [0], SubItems [1], StringToWindowState (SubItems [2]));
+			end;
+			SavePreferences;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.ToolClick(Sender: TObject);
+var
+	WorkDir: PChar;
+	StartupInfo: TStartupInfo;
+	ProcessInfo: TProcessInformation;
+begin
+	with TToolsListItem ((Sender as TMenuItem).Tag) do begin
+		FillChar (StartupInfo, SizeOf (StartupInfo), 0);
+		StartupInfo.cb := SizeOf (StartupInfo);
+		if Length (WorkingDir) > 0 then
+			WorkDir := PChar (WorkingDir)
+		else
+			WorkDir := nil;
+		StartupInfo.dwFlags := StartF_UseShowWindow;
+		case WindowState of
+			wsMaximized:
+				StartupInfo.wShowWindow := SW_SHOWMAXIMIZED;
+			wsMinimized:
+				StartupInfo.wShowWindow := SW_SHOWMINIMIZED;
+			else
+				StartupInfo.dwFlags := 0;
+		end;
+		if CreateProcess (nil, PChar (CommandLine), nil, nil, False, CREATE_NEW_PROCESS_GROUP or DETACHED_PROCESS, nil, WorkDir, StartupInfo, ProcessInfo) then begin
+			CloseHandle (ProcessInfo.hProcess);
+			CloseHandle (ProcessInfo.hThread);
+		end else
+			ShowDefaultMessageBox ('An error occurred while trying to start the application.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TMainForm.AddTool(const Title, CommandLine, WorkingDir: string; WindowState: TWindowState);
+var
+	O: TToolsListItem;
+begin
+	O := TToolsListItem (Self.ToolsList.Add);
+	O.Title := Title;
+	O.CommandLine := CommandLine;
+	O.WorkingDir := WorkingDir;
+	O.WindowState := WindowState;
+	O.MenuItem := TMenuItem.Create (Self);
+	with O.MenuItem do begin
+		Tag := Integer (O);
+		Caption := Title;
+		Hint := CommandLine;
+		OnClick := ToolClick;
+	end;
+	MainMenuTools.Insert (MainMenuTools.Count, O.MenuItem);
+end;
+
+procedure TMainForm.ProjectTreeStartDrag(Sender: TObject;
+	var DragObject: TDragObject);
+begin
+	DragObject := TNoImageDragObject.Create (Sender as TControl);
+end;
+
+procedure TMainForm.UpdateProgramOutput;
+begin
+	ActionProjectShowProgramOutput.Enabled := (MainConsole.LastOutSize > 2) or (MainConsole.LastErrSize > 2);
+end;
+
+procedure TMainForm.ShowProgramOutput(Sender: TObject);
+begin
+	with TProgramOutputForm.Create (Self) do try
+		OutputMemo.Text := MainConsole.LastOutText;
+		ErrorMemo.Text := MainConsole.LastErrText;
+		ShowModal;
+	finally
+		Free;
+	end;
+end;
+
+procedure TMainForm.ClearDebugInfo;
+begin
+end;
+
+procedure TMainForm.FileNewFolder(Sender: TObject);
+var
+	ParentNode,
+	Node: TTreeNode;
+	Folder: TFolder;
+begin
+	ParentNode := ProjectTree.Selected;
+	while Assigned (ParentNode) and Assigned (ParentNode.Data) and (not (TObject (ParentNode.Data) is TFolder)) do
+		ParentNode := ParentNode.Parent;
+	if Assigned (ParentNode) and Assigned (ParentNode.Parent) then begin
+		Folder := TFolder.Create;
+		Node := ProjectTree.Items.AddChildObject (ParentNode, 'New Folder', Folder);
+		Folder.TreeItem := Node;
+		with Node do begin
+			ImageIndex    := 0;
+			SelectedIndex := 1;
+      Selected := True;
+			EditText;
+		end;
+	end;
+end;
+
+function TMainForm.GetSourceTypeFolder(Node: TTreeNode): TTreeNode;
+begin
+	if Assigned (Node) and Assigned (Node.Parent) then begin
+		Result := Node;
+		while Assigned (Result) and Assigned (Result.Data) do
+			Result := Result.Parent;
+	end else
+		Result := nil;
+end;
+
+function TMainForm.FindFileInsertionPoint(ParentNode: TTreeNode): TTreeNode;
+begin
+	if Assigned (ParentNode) then begin
+		Result := ParentNode.GetFirstChild;
+		while Assigned (Result) and Assigned (Result.Data) and (TObject (Result.Data) is TSourceFile) do
+			Result := Result.GetNextSibling;
+	end else
+		Result := nil;
+end;
+
+function TMainForm.CreateFileNode(ParentNode: TTreeNode; SourceFile: TSourceFile): TTreeNode;
+begin
+	if Assigned (SourceFile.Folder) then
+		ParentNode := SourceFile.Folder.TreeItem;
+	if Assigned (ParentNode) then begin
+		Result := FindFileInsertionPoint (ParentNode);
+		if Assigned (Result) then
+			Result := ProjectTree.Items.InsertObject (Result, SourceFile.SourceName, SourceFile)
+		else
+			Result := ProjectTree.Items.AddChildObject (ParentNode, SourceFile.SourceName, SourceFile);
+	end else
+		Result := nil;
+end;
+
+procedure TMainForm.FileNewFile(Sender: TObject);
+var
+	Node: TTreeNode;
+begin
+	if Assigned (ProjectTree.Selected) then begin
+		Node := GetSourceTypeFolder (ProjectTree.Selected);
+		if Assigned (Node) then
+			if Node.Index = THeaderSourceFile.GetClassTreeIndex then
+				FileNewHeaderFile (Sender)
+			else if Node.Index = TCSourceFile.GetClassTreeIndex then
+				FileNewCSourceFile (Sender)
+			else if Node.Index = TGNUAsmSourceFile.GetClassTreeIndex then
+				FileNewGNUAssemblerSourceFile (Sender)
+			else if (ssA68k in SpecialSupport) and (Node.Index = TAsmSourceFile.GetClassTreeIndex) then
+				FileNewAssemblerSourceFile (Sender)
+			else if (ssQuill in SpecialSupport) and (Node.Index = TQuillSourceFile.GetClassTreeIndex) then
+				FileNewQuillSourceFile (Sender)
+			else if Node.Index = TNormalTextSourceFile.GetClassTreeIndex then
+				FileNewTextFile (Sender);
+	end;
+end;
+
+function TMainForm.GetSelectedFolder(SourceClass: TSourceFileClass): TFolder;
+var
+	Node: TTreeNode;
+begin
+	Result := nil;
+	Node := ProjectTree.Selected;
+	while Assigned (Node) and (Node <> TopNode.Item [SourceClass.GetClassTreeIndex]) do begin
+		if (not Assigned (Result)) and Assigned (Node.Data) and (TObject (Node.Data) is TFolder) then
+			Result := Node.Data;
+		Node := Node.Parent;
+	end;
+	if not Assigned (Node) then
+		Result := nil;
+end;
+
+procedure TMainForm.ErrorListKeyDown(Sender: TObject; var Key: Word;
+	Shift: TShiftState);
+var
+	S: string;
+	Item: TListItem;
+begin
+	if ((Key = VK_INSERT) or (Key = Ord('C'))) and (Shift = [ssCtrl]) then
+		with ErrorList do begin
+			S := '';
+			Item := Selected;
+			while Assigned (Item) do begin
+				S := S + Item.Caption + #13#10;
+				Item := GetNextItem (Item, sdAll, [isSelected]);
+			end;
+			Clipboard.AsText := S;
+		end;
+end;
+
+{$IFDEF CODINGEXT}
+procedure TMainForm.InitCodingExt;
+var
+	 ActionFindSymbol: TAction;
+begin
+	// Find Symbol declaration tool
+	ActionFindSymbol := TAction.Create(Self);
+	with ActionFindSymbol do
+	begin
+		ActionList := Actions;
+		Caption := 'Find Symbol Declaration';
+		Category := 'Extension';
+		OnExecute := ActionFindSymbolExecute;
+	end;
+
+	InsertsAction(Self, [OpenFileAtCursor1, OpenFileatCursor2], ActionFindSymbol);
+end;
+
+procedure TMainForm.ActionFindSymbolExecute(Sender: TObject);
+begin
+	CompForm.FindSymbolDecl;
+end;
+{$ENDIF}
+
+end.
+

+ 735 - 0
tigcc/ide/MasterUnit.pas

@@ -0,0 +1,735 @@
+unit MasterUnit;
+
+interface
+
+uses
+	CalcUnit, ProcessUnit, ParsingUnit,
+	LinkUnit,
+	Classes, Graphics, SourceEditUnit;
+
+const
+	IDELocation          = 'Bin\';
+	LinkLibLocation      = 'Bin\';
+	GCCLocation          = 'Bin\';
+	AsLocation           = 'Bin\';
+	A68kLocation         = 'Bin\';
+	PackLocation         = 'Bin\';
+	ASMIncludeLocation   = 'Include\ASM\';
+	GASIncludeLocation   = 'Include\S\';
+	CIncludeLocation     = 'Include\C\';
+	QuillIncludeLocation = 'Include\Quill\';
+	DocLocation          = 'Doc\';
+	ProjectsLocation     = 'Projects\';
+	StdLibLocation       = 'Lib\';
+	TIPatchLocation      = 'Lib\';
+	PStarterLocation     = 'Lib\';
+	TemplatesLocation    = 'Bin\';
+	CompletionLocation   = 'Include\C\Completion\';
+
+	DefaultGCCSwitches      = '-B .\ -I- -I ..\Include\C\';
+	DefaultAsSwitches       = '-mc68000 -I ..\Include\S\';
+	DefaultA68kSwitches     = '-i..\Include\ASM';
+	SpecialQuillGCCSwitches = '-I ..\Include\Quill\';
+
+	ProjectFileExt = '.tpr';
+
+	MaxNameLength = 8;
+
+type
+	TSpecialSupportOption = (ssA68k, ssQuill, ssPack, ssFlashOS, ssFargo);
+	TSpecialSupport = set of TSpecialSupportOption;
+	TProjectTarget = (ptRegular, ptFlashOS, ptFargo, ptArchive);
+	TTransferTarget = (ttNone, ttVTI, ttCalc);
+	TCurVTIType = (cvNone, cvTI89, cvTI92Plus, cvTI92);
+	TKernelFormat = (kfUnknown, kfNone, kfStandard, kfCompressedTables);
+	TRelocFormat = (rfUnknown, rfNone, rfDirect, rfAMS, rfKernel, rfCompressed, rfFLine);
+
+	TPredefinedLibOptions = class(TObject)
+		CalcDests: TCalcDests;
+		OptimizeCalcConsts: Boolean;
+		KernelFormat: TKernelFormat;
+		UseMinAMS: Boolean;
+		MinAMS: string;
+		UnofficialOSSupport: Boolean;
+		RelocFormat,
+		ROMCallFormat,
+		BSSRefFormat,
+		DataRefFormat: TRelocFormat;
+		UseFLineJumps,
+		Use4ByteFLineJumps,
+		OptimizeROMCalls,
+		UseInternalFLineEmulator: Boolean;
+		UseReturnValue,
+		EnableErrorReturn: Boolean;
+		SaveScreen: Boolean;
+		function GetSwitches: string;
+	end;
+
+var
+	MainConsole: TProcessConsole;
+	StopOnErrors,
+	DeleteAssemblyFiles,
+	DeleteObjectFiles,
+	AssumeUndefined,
+	AutoBlocks,
+	AutoNews,
+	UseDataVar,
+	DataVarCopy,
+	DataVarCopyIfArchived,
+	Pack,
+	DebugInfo,
+	StdLib,
+	InitBSS,
+	OptimizeNOPs,
+	OptimizeReturns,
+	OptimizeBranches,
+	OptimizeMoves,
+	OptimizeTests,
+	OptimizeCalculations,
+	RemoveUnusedSections,
+	CutUnusedRanges,
+	ReorderSections,
+	MergeConstants,
+	OutputBin: Boolean;
+	ProjectTarget: TProjectTarget;
+	GCCSwitches,
+	AsSwitches,
+	AsmSwitches,
+	DataVar,
+	PackVar,
+	CommandLine,
+	PostBuildProcessFile: string;
+	PredefinedLibOptions: TPredefinedLibOptions;
+	ProxyName: string;
+	ProxyPort: Integer;
+	TIGCCFolder: string;
+	Temp: string;
+	OperationCancelled,
+	OperationSuccessful: Boolean;
+	ProjectFileName: string;
+	SyntaxC,
+	SyntaxAsmGNU,
+	SyntaxAsm,
+	SyntaxQuill: TSyntaxColoring;
+	TabSizeC,
+	TabSizeAsm: Integer;
+	EditorColor: TColor;
+	EditorFont: TFont;
+	EditorOnFly,
+	EditorDragDrop,
+	EditorRemoveTrSp: Boolean;
+	LastNewsDate: Integer;
+	TransferTarget: TTransferTarget;
+	VTIPath: string;
+	LinkPort: TLinkPort;
+	LinkCable: TLinkCableType;
+	SpecialSupport: TSpecialSupport;
+	Compiling,
+	CompFinishAndStop,
+	CompStopNow: Boolean;
+	CompStartTime,
+	CompFileStartTime,
+	CompLastTime: TDateTime;
+	CompStartFile: procedure of object;
+	CompStop: procedure of object;
+	CompSetMessage: procedure(const Msg: string) of object;
+	CompUpdate: procedure of object;
+	CompUpdateProgramOutput: procedure of object;
+
+{$IFDEF CanSplit}
+var
+	SplitFiles: Boolean;
+{$ENDIF}
+
+function StartsWith(const SubStr: string; var Str: string; CaseSensitive: Boolean = False; Remove: Boolean = False): Boolean;
+
+procedure WaitForMainConsole(const ProcessDesc: string);
+
+function Runnable: Boolean;
+
+implementation
+
+uses
+	SysUtils, Forms;
+
+procedure WaitForMainConsole(const ProcessDesc: string);
+begin
+	CompUpdate;
+	while MainConsole.Running do begin
+		CompUpdate;
+		Application.ProcessMessages;
+		if CompFinishAndStop then begin
+			OperationCancelled := True;
+			CompSetMessage ('Finishing ' + ProcessDesc + ' Process');
+		end;
+		if CompStopNow then begin
+			OperationCancelled := True;
+			MainConsole.KillProcess;
+			Break;
+		end;
+	end;
+	CompUpdate;
+end;
+
+function Runnable: Boolean;
+begin
+	Result := (ProjectTarget <> ptArchive) and (TransferTarget <> ttNone);
+end;
+
+function StartsWith(const SubStr: string; var Str: string; CaseSensitive: Boolean; Remove: Boolean): Boolean;
+begin
+	if CaseSensitive then
+		Result := Copy (Str, 1, Length (SubStr)) = SubStr
+	else
+		Result := UpperCase (Copy (Str, 1, Length (SubStr))) = UpperCase (SubStr);
+	if Remove and Result then
+		Delete (Str, 1, Length (SubStr));
+end;
+
+{ TPredefinedLibOptions }
+
+function TPredefinedLibOptions.GetSwitches: string;
+procedure AddSwitch(Define: string; const Value: string = '');
+begin
+	if Length (Result) > 0 then
+		Result := Result + ' ';
+	Define := '-D' + Define;
+	if Length (Value) > 0 then
+		Define := '"' + Define + '=' + Value + '"';
+	Result := Result + Define;
+end;
+begin
+	Result := '';
+	if cdTI92 in CalcDests then
+		AddSwitch ('USE_TI92');
+	if cdTI89 in CalcDests then
+		AddSwitch ('USE_TI89');
+	if cdTI92Plus in CalcDests then
+		AddSwitch ('USE_TI92PLUS');
+	if cdV200 in CalcDests then
+		AddSwitch ('USE_V200');
+	if OptimizeCalcConsts then
+		AddSwitch ('OPTIMIZE_CALC_CONSTS');
+	if KernelFormat in [kfStandard, kfCompressedTables] then begin
+		AddSwitch ('USE_KERNEL');
+		if KernelFormat = kfCompressedTables then
+			AddSwitch ('USE_PREOS_COMPRESSED_TABLES');
+	end;
+	if UseMinAMS then try
+		AddSwitch ('MIN_AMS', IntToStr (Round (StrToFloat (MinAMS) * 100)));
+	except end;
+	if UnofficialOSSupport then
+		AddSwitch ('UNOFFICIAL_OS_SUPPORT');
+	if KernelFormat = kfCompressedTables then begin
+		if BSSRefFormat = rfNone then
+			AddSwitch ('MERGE_BSS');
+	end else begin
+		case RelocFormat of
+			rfKernel:      AddSwitch ('KERNEL_FORMAT_RELOCS');
+			rfCompressed:  AddSwitch ('COMPRESSED_FORMAT_RELOCS');
+			rfFLine:       AddSwitch ('USE_FLINE_JUMPS');
+		end;
+		case ROMCallFormat of
+			rfKernel:      AddSwitch ('KERNEL_FORMAT_ROM_CALLS');
+			rfCompressed:  AddSwitch ('COMPRESSED_FORMAT_ROM_CALLS');
+			rfFLine: begin
+				AddSwitch ('USE_FLINE_ROM_CALLS');
+				Result := Result + ' -fno-function-cse';
+			end;
+		end;
+		case BSSRefFormat of
+			rfNone:        AddSwitch ('MERGE_BSS');
+			rfKernel:      AddSwitch ('KERNEL_FORMAT_BSS');
+			rfCompressed:  AddSwitch ('COMPRESSED_FORMAT_BSS');
+		end;
+	end;
+	case DataRefFormat of
+		rfKernel:      AddSwitch ('KERNEL_FORMAT_DATA_VAR');
+		rfCompressed:  AddSwitch ('COMPRESSED_FORMAT_DATA_VAR');
+	end;
+	if UseFLineJumps then begin
+		AddSwitch ('USE_FLINE_JUMPS');
+		if Use4ByteFLineJumps then
+			AddSwitch ('USE_4_BYTE_FLINE_JUMPS');
+	end;
+	if OptimizeROMCalls then
+		AddSwitch ('OPTIMIZE_ROM_CALLS');
+	if UseInternalFLineEmulator then
+		AddSwitch ('USE_INTERNAL_FLINE_EMULATOR');
+	if UseReturnValue then
+		AddSwitch ('RETURN_VALUE');
+	if EnableErrorReturn then
+		AddSwitch ('ENABLE_ERROR_RETURN');
+	if SaveScreen then
+		AddSwitch ('SAVE_SCREEN');
+end;
+
+initialization
+	PredefinedLibOptions := TPredefinedLibOptions.Create;
+	PredefinedLibOptions.MinAMS := '1.01';
+	MainConsole := TProcessConsole.Create;
+	SyntaxC := TSyntaxColoring.Create (nil);
+	SyntaxAsm := TSyntaxColoring.Create (nil);
+	SyntaxAsmGNU := TSyntaxColoring.Create (nil);
+	SyntaxQuill := TSyntaxColoring.Create (nil);
+	EditorFont := TFont.Create;
+	with SyntaxC do begin
+		Enabled := True;
+		SymbolColor := clOlive;
+		SymbolStyle := [fsBold];
+		SymbolCustomStyle := True;
+		NumberColor := clMaroon;
+		NumberStyle := [];
+		NumberCustomStyle := False;
+		with WordLists.Add do begin
+			Caption := 'C Keywords';
+			Words.CommaText :=
+				'__alignof__,__asm__,__attribute__,__complex__,__const__,__extension__,__imag__,__inline__,__label__,__real__,__typeof__,' +
+				'asm,auto,break,case,char,const,continue,default,do,double,else,enum,extern,float,for,goto,if,inline,int,long,register,return,short,signed,sizeof,static,struct,switch,typedef,typeof,union,unsigned,void,volatile,while';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := clBlue;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Comment Area';
+			CustomColor := True;
+			Color := clGreen;
+			CustomStyle := True;
+			Style := [fsItalic];
+			BeginText := '/*';
+			EndText := '*/';
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Comment Line';
+			CustomColor := True;
+			Color := clGreen;
+			CustomStyle := True;
+			Style := [fsItalic];
+			BeginText := '//';
+			EndText := #13;
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'String';
+			CustomColor := True;
+			Color := clMaroon;
+			CustomStyle := False;
+			Style := [];
+			BeginText := '"';
+			EndText := '"';
+			IgnoreChar := '\';
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Character';
+			CustomColor := True;
+			Color := clMaroon;
+			CustomStyle := False;
+			Style := [];
+			BeginText := '''';
+			EndText := '''';
+			IgnoreChar := '\';
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Preprocessor Directive';
+			CustomColor := True;
+			Color := clTeal;
+			CustomStyle := True;
+			Style := [fsBold];
+			BeginText := '#';
+			EndText := ' ';
+			Switchable := False;
+		end;
+		ParenthesisColors.CommaText := '$800080,$C08000,$8080FF,$008000';
+		ParenthesisStyle := [fsBold];
+		ParenthesisCustomStyle := True;
+	end;
+	with SyntaxAsmGNU do begin
+		NumberColor := SyntaxC.NumberColor;
+		NumberStyle := SyntaxC.NumberStyle;
+		NumberCustomStyle := SyntaxC.NumberCustomStyle;
+		SymbolColor := SyntaxC.SymbolColor;
+		SymbolStyle := SyntaxC.SymbolStyle;
+		SymbolCustomStyle := SyntaxC.SymbolCustomStyle;
+		ParenthesisColors.Assign (SyntaxC.ParenthesisColors);
+		ParenthesisStyle := SyntaxC.ParenthesisStyle;
+		ParenthesisCustomStyle := SyntaxC.ParenthesisCustomStyle;
+		with CustomStyles.Add do begin
+			Caption := 'Comment Area';
+			CustomColor := True;
+			Color := clGreen;
+			CustomStyle := True;
+			Style := [fsItalic];
+			BeginText := '/*';
+			EndText := '*/';
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Comment Line (|)';
+			CustomColor := True;
+			Color := clGreen;
+			CustomStyle := True;
+			Style := [fsItalic];
+			BeginText := '|';
+			EndText := #13;
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Comment Line (#)';
+			CustomColor := True;
+			Color := clGreen;
+			CustomStyle := True;
+			Style := [fsItalic];
+			BeginText := '#';
+			EndText := #13;
+			Switchable := False;
+			LineStartOnly := True;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'String';
+			CustomColor := True;
+			Color := clMaroon;
+			CustomStyle := False;
+			Style := [];
+			BeginText := '"';
+			EndText := '"';
+			IgnoreChar := '\';
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'Character';
+			CustomColor := True;
+			Color := clMaroon;
+			CustomStyle := False;
+			Style := [];
+			BeginText := '''';
+			EndText := '''';
+			IgnoreChar := '\';
+			Switchable := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Data Movement';
+			Words.CommaText := 'EXG,LEA,LINK,MOV,MOVE,MOVEA,MOVEM,MOVEP,MOVEQ,MOVM,MOVP,MOVQ,PEA,UNLK';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Integer Arithmetic';
+			Words.CommaText := 'ADD,ADDA,ADDI,ADDQ,ADDX,CLR,CMP,CMPA,CMPI,CMPM,DIVS,DIVU,EXT,MULS,MULU,NEG,NEGX,SUB,SUBA,SUBI,SUBQ,SUBX';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Logical Instructions';
+			Words.CommaText := 'AND,ANDI,EOR,EORI,NOT,OR,ORI';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Shift/Rotation Instructions';
+			Words.CommaText := 'ASL,ASR,LSL,LSR,ROL,ROR,ROXL,ROXR,SWAP';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Bit Manipulation';
+			Words.CommaText := 'BCHG,BCLR,BSET,BTST';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Program Control';
+			Words.CommaText := 'BCC,BCS,BEQ,BGE,BGT,BHI,BLE,BLS,BLT,BMI,BNE,BPL,BRA,BSR,BVC,BVS,JBCC,JBCS,JBEQ,JBGE,JBGT,JBHI,JBLE,JBLS,JBLT,JBMI,JBNE,JBPL,JBRA,JBSR,JBVC,JBVS,JSR,JRA,JMP,'
+				+ 'NOP,RTR,RTS,SCC,SCS,SEQ,SF,SGE,SGT,SHI,SLE,SLS,SLT,SMI,SNE,SPL,ST,SVC,SVS,TST,'
+				+ 'JHI,JLS,JCC,JCS,JNE,JEQ,JVC,JVS,JPL,JMI,JGE,JLT,JGT,JLE,DBHI,DBLS,DBCC,DBCS,DBNE,DBEQ,DBVC,DBVS,DBPL,DBMI,DBGE,DBLT,DBGT,DBLE,DBF,DBRA,DBT,'
+				+ 'FJNE,FJEQ,FJGE,FJLT,FJGT,FJLE,FJF,FJT,FJGL,FJGLE,FJNGE,FJNGL,FJNGLE,FJNGT,FJNLE,FJNLT,FJOGE,FJOGL,FJOGT,FJOLE,FJOLT,FJOR,FJSEQ,FJSF,FJSNE,FJST,FJUEQ,FJUGE,FJUGT,FJULE,FJULT,FJUN';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'System Control';
+			Words.CommaText := 'ILLEGAL,RTE,TRAP';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Extensions';
+			Words.CommaText := 'B,L,S,W';
+			Color := $408000;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Assembler Directives';
+			Words.CommaText := 'abort,align,ascii,asciz,balign,balignw,balignl,byte,comm,data,'
+				+ 'def,dim,double,eject,else,end,elseif,endef,endfunc,endif,endm,endr,equ,equiv,'
+				+ 'err,even,exitm,extern,fail,file,fill,float,func,global,hword,ident,if,include,'
+				+ 'incbin,int,irp,irpc,lcomm,lflags,line,ln,list,long,macro,mri,nolist,octa,org,'
+				+ 'p2align,p2alignw,p2alignl,print,psize,purgem,quad,rept,sbttl,scl,section,set,'
+				+ 'short,single,size,sleb128,skip,space,stabd,stabn,stabs,string,struct,tag,text,'
+				+ 'title,type,uleb128,val,vtable_entry,word';
+			Color := clBlue;
+			CustomColor := True;
+			Style := [fsBold];
+			CustomStyle := True;
+			CaseSensitive := True;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Registers';
+			Words.CommaText := 'a0,a1,a2,a3,a4,a5,a6,a7,d0,d1,d2,d3,d4,d5,d6,d7,fp,pc,sp,sr';
+			Color := clRed;
+			CustomColor := True;
+			Style := [fsUnderline];
+			CustomStyle := True;
+			CaseSensitive := False;
+		end;
+	end;
+	with SyntaxAsm do begin
+		NumberColor := SyntaxC.NumberColor;
+		NumberStyle := SyntaxC.NumberStyle;
+		NumberCustomStyle := SyntaxC.NumberCustomStyle;
+		SymbolColor := SyntaxC.SymbolColor;
+		SymbolStyle := SyntaxC.SymbolStyle;
+		SymbolCustomStyle := SyntaxC.SymbolCustomStyle;
+		ParenthesisColors.Assign (SyntaxC.ParenthesisColors);
+		ParenthesisStyle := SyntaxC.ParenthesisStyle;
+		ParenthesisCustomStyle := SyntaxC.ParenthesisCustomStyle;
+		with CustomStyles.Add do begin
+			Caption := 'Comment';
+			CustomColor := True;
+			Color := clGreen;
+			CustomStyle := True;
+			Style := [fsItalic];
+			BeginText := ';';
+			EndText := #13;
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'String (double-quoted)';
+			CustomColor := True;
+			Color := clMaroon;
+			CustomStyle := False;
+			Style := [];
+			BeginText := '"';
+			EndText := '"';
+			IgnoreChar := '';
+			Switchable := False;
+		end;
+		with CustomStyles.Add do begin
+			Caption := 'String (single-quoted)';
+			CustomColor := True;
+			Color := clMaroon;
+			CustomStyle := False;
+			Style := [];
+			BeginText := '''';
+			EndText := '''';
+			IgnoreChar := '';
+			Switchable := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Data Movement';
+			Words.CommaText := 'EXG,LEA,LINK,MOV,MOVE,MOVEA,MOVEM,MOVEP,MOVEQ,PEA,UNLK';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Integer Arithmetic';
+			Words.CommaText := 'ADD,ADDA,ADDI,ADDQ,ADDX,CLR,CMP,CMPA,CMPI,CMPM,DIVS,DIVU,EXT,MULS,MULU,NEG,NEGX,SUB,SUBA,SUBI,SUBQ,SUBX';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Logical Instructions';
+			Words.CommaText := 'AND,ANDI,EOR,EORI,NOT,OR,ORI';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Shift/Rotation Instructions';
+			Words.CommaText := 'ASL,ASR,LSL,LSR,ROL,ROLX,ROR,RORX,ROXL,ROXR,SWAP';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Bit Manipulation';
+			Words.CommaText := 'BCHG,BCLR,BSET,BTST';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Program Control';
+			Words.CommaText := 'BCC,BCS,BEQ,BGE,BGT,BHI,BHS,BLE,BLO,BLS,BLT,BMI,BNE,BPL,BRA,BSR,BVC,BVS,DBCC,DBCS,DBEQ,DBF,DBGE,DBGT,DBHI,DBHS,DBLE,DBLO,DBLS,DBLT,DBMI,DBNE,DBPL,DBRA,DBT,DBVC,DBVS,JMP,JSR,NOP,RTR,RTS,'
+				+ 'SCC,SCS,SEQ,SF,SGE,SGT,SHI,SHS,SLE,SLO,SLS,SLT,SMI,SNE,SPL,ST,SVC,SVS,TST';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'System Control';
+			Words.CommaText := 'ILLEGAL,RTE,TRAP';
+			Color := clBlue;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Extensions';
+			Words.CommaText := 'B,L,S,W';
+			Color := $408000;
+			CustomColor := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Assembler Directives';
+			Words.CommaText := 'BSS,CNOP,CSEG,DSEG,DC,DCB,DS,END,ENDC,ENDIF,ENDM,EQU,EQUR,EVEN,FAR,IDNT,IFC,IFD,IFEQ,IFGE,IFGT,IFLE,IFLT,IFNC,IFND,IFNE,INCBIN,INCLUDE,LIST,MACRO,NEAR,NOLIST,ORG,PAGE,PUBLIC,REG,RORG,SECTION,SET,SPC,TITLE,TTL,XDEF,XREF';
+			Color := clBlue;
+			CustomColor := True;
+			Style := [fsBold];
+			CustomStyle := True;
+			CaseSensitive := False;
+		end;
+		with WordLists.Add do begin
+			Caption := 'Registers';
+			Words.CommaText := 'a0,a1,a2,a3,a4,a5,a6,a7,d0,d1,d2,d3,d4,d5,d6,d7,fp,pc,sp,sr';
+			Color := clRed;
+			CustomColor := True;
+			Style := [fsUnderline];
+			CustomStyle := True;
+			CaseSensitive := False;
+		end;
+	end;
+	SyntaxQuill.Assign (SyntaxC);
+	with SyntaxQuill do begin
+		with WordLists.Add do begin
+			Caption := 'Sections';
+			Words.CommaText := '$$ACTIONS,$$CONNECTIONS,$$END,$$END_TEST,$$EVENTS,$$EXTERN,$$LOCATIONS,$$MESSAGES,$$OBJECTS,$$OLDSTYLE_SYSTEM_MESSAGES,$$PICTURES,$$PICTURES_TEST,$$SYSTEM_MESSAGES,$$TITLE,$$VOCABULARY';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $0000FF;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Section-specific Keywords';
+			Words.CommaText := 'ACTION,BITMAP,CBLOCK,CONN,DEFINE,DRAWING,END_BITMAP,END_CBLOCK,END_DRAWING,END_PACKED_BITMAP,EVENT,FROM,LOC,MSG,OBJ,PACKED_BITMAP,WORD';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $808040;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Additional Keywords';
+			Words.CommaText := 'CONTINUE,ELSE';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $808040;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Non-functional Keywords';
+			Words.CommaText := 'BEEP,BLOCK,BORDER,BRIGHT,FLASH,INK,PAPER';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $C0C0C0;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Predefined Aliases';
+			Words.CommaText := '$ALSOSEE,$ARG,$CARRIED,$CENTER,$CNT1,$CNT2,$CNT3,$CNT4,$CONT,$CURLOC,$DARK,$DARKCNT,$DESC,$DESC_CNT,$DESC_DARKCNT,$DESC_NOLIGHTCNT,$DONE,$ENDGAME,$EXIT,$FAIL,$FONT,$FULLSCR,$GCONTROL,$LSOURCE,'
+				+ '$MAXCAR,$NOLIGHTCNT,$NOUN,$NOWHERE,$NULL,$NUMCAR,$PROMPT,$RESTART,$SCORE,$SPECIAL,$SUBROUTINE,$TURNHI,$TURNLO,$VERB,$WORN';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $800080;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Conditions';
+			Words.CommaText := 'ABSENT,AT,ATGT,ATLT,CARRIED,CHANCE,CREATED,EQ,EQWORD,EXTWORD,GT,HERE,ISAT,ISDESC,ISNOTAT,ISNOTNULL,ISNULL,LT,NEQWORD,NOTAT,NOTCARR,NOTCREATED,NOTEQ,NOTHERE,NOTSAME,NOTWORN,NOTZERO,PRESENT,SAME,TRYMOVE,WORN,ZERO';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $FF0000;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Actions';
+			Words.CommaText := 'ADD,ALSOSEE,ANYKEY,AUTOD,AUTOG,AUTOR,AUTOW,BIGFONT,CANCEL,CLEAR,CLS,COPYFF,COPYFO,COPYOF,COPYOO,CREATE,DECCAR,DESC,DESTROY,DONE,DROP,DROPALL,END,ENDDESC,EXIT,EXTERN,GET,GETWORD,GOTO,INCCAR,INVEN,LET,'
+				+ 'LISTAT,LISTOBJ,LOAD,MAXCAR,MES,MESFLAG,MESSAGE,MINUS,NEWLINE,NOTDONE,OK,PAUSE,PICNORM,PICOFF,PICON,PLACE,PLUS,PRINT,PROMPT,PUTO,QUIT,QVERSION,RAMLOAD,RAMSAVE,RANDOM,REDRAW,REMOVE,RESTART,SAVE,SCORE,'
+				+ 'SET,SETNOUN,SETVERB,SHOWLOC,SMLFONT,SUB,SWAP,SYSMESS,TURNS,WEAR,WHATO,WHEREO,ZAPSCR';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $A00000;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Drawing Primitives';
+			Words.CommaText := 'AMOVE,CALL,ELLIPSE,FILL,INV_ELLIPSE,INV_LINE,INV_PLOT,INV_RPLOT,LINE,MOVE,PLOT,RPLOT,SHADE,XOR_ELLIPSE,XOR_LINE,XOR_PLOT,XOR_RPLOT';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $FF8000;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Drawing Directions';
+			Words.CommaText := 'DOWN,DOWN_LEFT,DOWN_RIGHT,LEFT,LEFT_DOWN,LEFT_UP,RIGHT,RIGHT_DOWN,RIGHT_UP,UP,UP_LEFT,UP_RIGHT';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $008000;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'Shading Patterns';
+			Words.CommaText := '$BKSLASHFILL,$BRICKFILL,$CHAINFILL,$CIRCLEFILL,$CLOSEDASHFILL,$CLOSEDOTFILL,$CLOSEWAVEFILL,$CROSSFILL,$DASHFILL,$DOTFILL,$HATCHFILL,$INTERLEAVEFILL,$LIGHTDOTFILL,$LIGHTLINEFILL,$LINEFILL,$SLASHFILL,'
+				+ '$SOLIDFILL,$SQDOTFILL,$SQUAREFILL,$THICKBKSLASHFILL,$THICKHATCHFILL,$THICKLINEFILL,$THICKSLASHFILL,$VDASHFILL,$VINTERLEAVEFILL,$VLDOTFILL,$VLIGHTLINEFILL,$VLINEFILL,$VTHICKLINEFILL,$WAVEFILL,$WIDEDOTFILL,$XMARKFILL,$ZIGZAGFILL';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $800080;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+		with WordLists.Add do begin
+			Caption := 'External Symbols';
+			Words.CommaText := '$ACTIONS$,$ARG$,$BMPUT$,$BPCKPUT$,$BUFFER$,$CONNECTIONS$,$EVENTS$,$EXTERN$,$FLAGS$,$FLAGS_BACKUP$,$GDF$,$GETLINE$,$LOCATIONS$,$LQL$,$MAXCAR$,$MESSAGES$,$NFLAG$,$NLOC$,$NMSG$,$NOBJ$,$NSYSMSG$,$NWORD$,'
+				+ '$OBJECTS$,$PDRAW$,$PICTURE$,$PRINT$,$RAM_SAVED$,$SCALEX$,$SCALEY$,$SSCR$,$SYSTEM_MESSAGES$,$WORDS$';
+			CaseSensitive := True;
+			CustomColor := True;
+			Color := $408000;
+			CustomStyle := True;
+			Style := [fsBold];
+		end;
+	end;
+	EditorFont.Name := 'Courier New';
+	EditorFont.Size := 10;
+	EditorColor := clWindow;
+	DecimalSeparator := '.';
+finalization
+	EditorFont.Free;
+	SyntaxQuill.Free;
+	SyntaxAsm.Free;
+	SyntaxAsmGNU.Free;
+	SyntaxC.Free;
+	MainConsole.Free;
+	PredefinedLibOptions.Free;
+end.

BIN
tigcc/ide/NewFolderUnit.dfm


+ 33 - 0
tigcc/ide/NewFolderUnit.pas

@@ -0,0 +1,33 @@
+unit NewFolderUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, ExtCtrls;
+
+type
+  TNewFolderForm = class(TForm)
+    Label1: TLabel;
+    InputBox: TEdit;
+    Bevel1: TBevel;
+    ButtonOK: TButton;
+    ButtonCancel: TButton;
+    procedure InputBoxChange(Sender: TObject);
+  private
+	public
+	end;
+
+var
+  NewFolderForm: TNewFolderForm;
+
+implementation
+
+{$R *.DFM}
+
+procedure TNewFolderForm.InputBoxChange(Sender: TObject);
+begin
+	ButtonOK.Enabled := InputBox.Text <> '';
+end;
+
+end.

BIN
tigcc/ide/NewsUnit.dfm


+ 250 - 0
tigcc/ide/NewsUnit.pas

@@ -0,0 +1,250 @@
+unit NewsUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	ScktComp, StdCtrls;
+
+const
+	NewsID = 'TIGCC News Format'#13#10#13#10;
+
+type
+	TNewsForm = class(TForm)
+		NewsClient: TClientSocket;
+		NewsBox: TScrollBox;
+		VisitButton: TButton;
+		CloseButton: TButton;
+		RetreiveLabel: TLabel;
+    ProxyCheckBox: TCheckBox;
+    ProxyNameEdit: TEdit;
+    Label1: TLabel;
+    ProxyPortEdit: TEdit;
+    RefreshButton: TButton;
+		procedure NewsClientError(Sender: TObject; Socket: TCustomWinSocket;
+			ErrorEvent: TErrorEvent; var ErrorCode: Integer);
+		procedure FormActivate(Sender: TObject);
+		procedure FormClose(Sender: TObject; var Action: TCloseAction);
+		procedure NewsClientConnect(Sender: TObject; Socket: TCustomWinSocket);
+		procedure NewsClientRead(Sender: TObject; Socket: TCustomWinSocket);
+		procedure ProxyCheckBoxClick(Sender: TObject);
+    procedure RefreshButtonClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+	private
+		FSilentConnect: Boolean;
+	public
+		Labels: array of TLabel;
+		procedure Connect;
+		function Execute: Boolean;
+		property SilentConnect: Boolean read FSilentConnect write FSilentConnect;
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	MasterUnit, MainUnit,
+	UtilsWin,
+	ShellAPI, Registry;
+
+procedure TNewsForm.Connect;
+var
+	I: Integer;
+begin
+	if not NewsClient.Active then begin
+		for I := High (Labels) downto Low (Labels) do
+			Labels[I].Free;
+		SetLength (Labels, 0);
+		RetreiveLabel.Show;
+		Update;
+		try
+			with NewsClient do begin
+				if ProxyCheckBox.Checked then begin
+					Host := '';
+					Address := '';
+					if (Pos ('.', ProxyNameEdit.Text) > 0) and (ProxyNameEdit.Text [1] in ['0'..'9']) then
+						Address := ProxyNameEdit.Text
+					else
+						Host := ProxyNameEdit.Text;
+					try
+						Port := StrToInt (ProxyPortEdit.Text);
+					except
+						Port := 8080;
+					end;
+				end else begin
+					Address := '';
+					Host := 'tigcc.ticalc.org';
+					Port := 80;
+				end;
+				NewsClient.Active := True;
+			end;
+		except
+			RetreiveLabel.Hide;
+			ShowDefaultMessageBox ('Error connecting to tigcc.ticalc.org. Please check your connection.', 'Error', mtProgramError);
+			if not Visible then
+				Free;
+		end;
+	end;
+end;
+
+function TNewsForm.Execute: Boolean;
+begin
+	Result := ShowModal = mrOK;
+	if Result then
+		ShellExecute (0, nil, 'http://tigcc.ticalc.org/', nil, nil, sw_ShowMaximized);
+end;
+
+procedure TNewsForm.NewsClientError(Sender: TObject;
+	Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
+	var ErrorCode: Integer);
+begin
+	NewsClient.Active := False;
+	RetreiveLabel.Hide;
+	ShowDefaultMessageBox ('Error downloading news from tigcc.ticalc.org. Please check your connection.', 'Error', mtProgramError);
+	if not Visible then
+		Free;
+end;
+
+procedure TNewsForm.FormActivate(Sender: TObject);
+begin
+	if not SilentConnect then
+		Connect;
+end;
+
+procedure TNewsForm.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+	NewsClient.Active := False;
+	ProxyName := ProxyNameEdit.Text;
+	try
+		if Length (ProxyPortEdit.Text) > 0 then
+			ProxyPort := StrToInt (ProxyPortEdit.Text)
+		else
+			ProxyPort := 0;
+	except end;
+end;
+
+procedure TNewsForm.NewsClientConnect(Sender: TObject;
+	Socket: TCustomWinSocket);
+var
+	Line: string;
+begin
+	Line := 'GET http://tigcc.ticalc.org/newsheadlines.txt';
+	if ProxyCheckBox.Checked then
+		Line := Line + ' HTTP/1.1'#13#10'Accept: */*'#13#10'Accept-Language: en'#13#10'User-Agent: TIGCC'#13#10'Host: tigcc.ticalc.org'#13#10'Proxy-Connection: Keep-Alive'#13#10;
+	Line := Line + #13#10;
+	Socket.SendText (Line);
+end;
+
+procedure TNewsForm.NewsClientRead(Sender: TObject;
+	Socket: TCustomWinSocket);
+var
+	S: string;
+	Date,
+	LastDate: Integer;
+	CurLabel: TLabel;
+begin
+	RetreiveLabel.Hide;
+	S := Socket.ReceiveText;
+	NewsClient.Active := False;
+	if Pos (NewsID, S) > 0 then begin
+		LastDate := 0;
+		Delete (S, 1, Pos (NewsID, S) - 1 + Length (NewsID));
+		while Pos (#13#10, S) > 0 do begin
+			if S [1] = #13 then
+				Break;
+			CurLabel := TLabel.Create (Self);
+			CurLabel.Left := 2;
+			if Length (Labels) > 0 then
+				with Labels [High (Labels)] do
+					CurLabel.Top := Top + Height + 2
+			else
+				CurLabel.Top := 0;
+			try
+				Date := StrToInt (Copy (S, 1, Pos (#13#10, S) - 1));
+				if LastDate = 0 then
+					LastDate := Date;
+			except
+				Date := 0;
+			end;
+			Delete (S, 1, Pos (#13#10, S) + 1);
+			with CurLabel.Font do begin
+				Name := 'Arial';
+				Size := 9;
+				Style := [fsBold];
+				if Date > LastNewsDate then
+					Color := $0000C0
+				else
+					Color := $808080;
+			end;
+			CurLabel.Caption := Copy (S, 1, Pos (#13#10, S) - 1);
+			Delete (S, 1, Pos (#13#10, S) + 1);
+			Delete (S, 1, Pos (#13#10, S) + 1);
+			CurLabel.Parent := NewsBox;
+			CurLabel.Show;
+			SetLength (Labels, Length (Labels) + 1);
+			Labels [High (Labels)] := CurLabel;
+		end;
+		if (LastDate > LastNewsDate) and (not Visible) then
+			Execute;
+		if LastNewsDate <> LastDate then begin
+			LastNewsDate := LastDate;
+			MainForm.SavePreferences;
+		end;
+	end else
+		ShowDefaultMessageBox ('Error in news format from tigcc.ticalc.org. Please contact the site administrator.', 'Error', mtProgramError);
+	if not Visible then
+		Free;
+end;
+
+procedure TNewsForm.ProxyCheckBoxClick(Sender: TObject);
+var
+	NewProxy: string;
+begin
+	ProxyNameEdit.Enabled := ProxyCheckBox.Checked;
+	ProxyPortEdit.Enabled := ProxyCheckBox.Checked;
+	if ProxyCheckBox.Checked then begin
+		with TRegistry.Create do try
+			RootKey := HKEY_CURRENT_USER;
+			if OpenKeyReadOnly ('\Software\Microsoft\Windows\CurrentVersion\Internet Settings') then begin
+				if ValueExists ('ProxyServer') then begin
+					NewProxy := ReadString ('ProxyServer');
+					if Pos ('http=', LowerCase (NewProxy)) > 0 then begin
+						Delete (NewProxy, 1, Pos ('http=', LowerCase (NewProxy)) - 1 + Length ('http='));
+						if Pos (';', NewProxy) > 0 then
+							Delete (NewProxy, Pos (';', NewProxy), Length (NewProxy));
+					end else
+						if Pos (';', NewProxy) > 0 then
+							NewProxy := '';
+					if Pos (':', NewProxy) > 0 then begin
+						ProxyNameEdit.Text := Copy (NewProxy, 1, Pos (':', NewProxy) - 1);
+						ProxyPortEdit.Text := Copy (NewProxy, Pos (':', NewProxy) + 1, Length (NewProxy));
+					end;
+				end;
+			end;
+		finally
+			Free;
+		end;
+	end else begin
+		ProxyNameEdit.Text := '';
+		ProxyPortEdit.Text := '';
+	end;
+end;
+
+procedure TNewsForm.RefreshButtonClick(Sender: TObject);
+begin
+	NewsClient.Active := False;
+	Connect;
+end;
+
+procedure TNewsForm.FormCreate(Sender: TObject);
+begin
+	ProxyCheckBox.Checked := Length (ProxyName) > 0;
+	ProxyNameEdit.Text := ProxyName;
+	if ProxyCheckBox.Checked then
+		ProxyPortEdit.Text := IntToStr (ProxyPort)
+	else
+		ProxyPortEdit.Text := '';
+end;
+
+end.

BIN
tigcc/ide/OpenFileStatusUnit.dfm


+ 33 - 0
tigcc/ide/OpenFileStatusUnit.pas

@@ -0,0 +1,33 @@
+unit OpenFileStatusUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  ComCtrls, StdCtrls, ExtCtrls;
+
+type
+	TOpenFileStatusForm = class(TForm)
+    FileAnimate: TAnimate;
+    FileNameLabel: TPanel;
+    procedure FormCreate(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
+  private
+	public
+	end;
+
+implementation
+
+{$R *.DFM}
+
+procedure TOpenFileStatusForm.FormCreate(Sender: TObject);
+begin
+	Screen.Cursor := crHourglass;
+end;
+
+procedure TOpenFileStatusForm.FormDestroy(Sender: TObject);
+begin
+	Screen.Cursor := crDefault;
+end;
+
+end.

+ 598 - 0
tigcc/ide/ParsingUnit.pas

@@ -0,0 +1,598 @@
+unit ParsingUnit;
+
+interface
+
+uses
+	CalcUnit,
+	SysUtils, Classes;
+
+const
+	LineIndicator = '#L';
+	OffsetIndicator = '#$';
+	PatchToken = '$$PATCH';
+	ErrorToken = '$$ERROR';
+	WarningToken = '$$WARNING';
+	ALineIdentifier = '_A_LINE';
+	FLineIdentifier = '_F_LINE';
+	SParseError = 'Line %d: Parse error before ''%s''';
+
+type
+	EFileParseError = class(Exception);
+
+	PBoolean = ^Boolean;
+
+	TLineChangeEvent = procedure(StartLine, Change: Integer) of object;
+	TLineContentsEvent = function(StartLine, EndLine: Integer): string of object;
+
+type
+	TCalcInt1 = packed record
+		Int: Byte;
+	end;
+	PCalcInt1 = ^TCalcInt1;
+
+	TCalcInt2 = packed record
+		Hi,
+		Lo: TCalcInt1;
+	end;
+	PCalcInt2 = ^TCalcInt2;
+
+	TCalcInt4 = packed record
+		Hi,
+		Lo: TCalcInt2;
+	end;
+	PCalcInt4 = ^TCalcInt4;
+
+	TPCInt1 = packed record
+		Int: Byte;
+	end;
+	PPCInt1 = ^TPCInt1;
+
+	TPCInt2 = packed record
+		Lo,
+		Hi: TPCInt1;
+	end;
+	PPCInt2 = ^TPCInt2;
+
+	TPCInt4 = packed record
+		Lo,
+		Hi: TPCInt2;
+	end;
+	PPCInt4 = ^TPCInt4;
+
+function ReadCalcInt(Int: TCalcInt1): Byte; overload;
+function ReadCalcInt(Int: TCalcInt2): Word; overload;
+function ReadCalcInt(Int: TCalcInt4): LongWord; overload;
+
+procedure WriteCalcInt(Input: Byte; out Int: TCalcInt1); overload;
+procedure WriteCalcInt(Input: Word; out Int: TCalcInt2); overload;
+procedure WriteCalcInt(Input: LongWord; out Int: TCalcInt4); overload;
+
+function ReadPCInt(Int: TPCInt1): Byte; overload;
+function ReadPCInt(Int: TPCInt2): Word; overload;
+function ReadPCInt(Int: TPCInt4): LongWord; overload;
+
+procedure WritePCInt(Input: Byte; out Int: TPCInt1); overload;
+procedure WritePCInt(Input: Word; out Int: TPCInt2); overload;
+procedure WritePCInt(Input: LongWord; out Int: TPCInt4); overload;
+
+type
+	TTFRes2 = array [0..1] of Byte;
+	TTFRes3 = array [0..2] of Byte;
+	TTFRes6 = array [0..5] of Byte;
+
+	TTransferFileHeader = packed record
+		Signature: array [0..7] of Char;  // "**TI92P*" or "**TI89**"
+		Reserved1: TTFRes2;               // 01 00
+		Folder: array [0..7] of Char;     // folder name
+		Desc: array [0..39] of Char;      // not used
+		Reserved2: TTFRes6;               // 01 00 52 00 00 00
+		VarName: array [0..7] of Char;    // variable name
+		LinkType: TPCInt1;                // variable link type (0C = string, 1C = other, 21 = program, ...)
+		Reserved3: TTFRes3;               // 00 00 00
+		FileSize: TPCInt4;                // file size from Signature to CheckSum
+		Reserved4: TTFRes6;               // A5 5A 00 00 00 00
+	end;
+	PTransferFileHeader = ^TTransferFileHeader;
+
+	TCalcVarHeader = packed record
+		DataSize: TCalcInt2;              // data size (including Tag)
+	end;
+	PCalcVarHeader = ^TCalcVarHeader;
+
+	TCalcVarFooter = packed record
+		Tag: TCalcInt1;                   // variable tag
+	end;
+	PCalcVarFooter = ^TCalcVarFooter;
+
+	TTransferFileFooter = packed record
+		CheckSum: TPCInt2;                // checksum from DataSize to Tag
+	end;
+	PTransferFileFooter = ^TTransferFileFooter;
+
+	TCalcOSFooter = packed record
+		CheckSum: TCalcInt4;              // encrypted checksum
+		SignatureHeader: TCalcInt2;       // 02 0D
+		SignatureType: TCalcInt1;         // 40
+		Signature: array [0..63] of Byte; // signature, encrypted using TI's private key
+	end;
+	PCalcOSFooter = ^TCalcOSFooter;
+
+	PBinData = PChar;
+
+const
+	MaxCalcAllocBlock = $FFF0;
+
+procedure ParseSFile(Contents: TStringList);
+procedure ParseDebugSFile(Contents: TStringList; OnLineChange: TLineChangeEvent; LineContents: TStringList; OnGetLineContents: TLineContentsEvent);
+procedure ParsePStarter(const InputFile: string; const OutputFile: string; const PackVar: string);
+
+procedure ParseDebugSFileDisk(Contents: TStringList; const SourceFileName: string);
+
+function GetCalcVarSize(ContentLength: LongWord; const Extension: string = ''): LongWord;
+function GetTransferFileSize(ContentLength: LongWord; const Extension: string = ''; OutputBin: Boolean = False): LongWord;
+procedure ProduceTransferFile(Output: Pointer; Contents: Pointer; ContentLength: LongWord; CalcDest: TCalcDest; const DestFolder, DestVarName: string; VarTag: Byte; const Extension: string = ''; OutputBin: Boolean = False);
+function GetTransferFileExt(CalcDest: TCalcDest; VarTag: Byte; OutputBin: Boolean = False): string;
+function GetOSUpgradeFileSize(ContentLength: LongWord; OutputBin: Boolean = True): LongWord;
+procedure ProduceOSUpgradeFile(Output: Pointer; Contents: Pointer; ContentLength: LongWord; OutputBin: Boolean = True);
+function GetOSUpgradeFileExt(CalcDest: TCalcDest; OutputBin: Boolean = False): string;
+
+var
+	ErrorMessageProc: procedure(const Msg: string) = nil;
+
+implementation
+
+uses
+	Windows, UtilsDos;
+
+{ General parsing procedures }
+
+procedure ParseSFile(Contents: TStringList);
+var
+	I,
+	P1,
+	P2: Integer;
+	RegRelative,
+	NeedFLine,
+	Changed: Boolean;
+	L: string;
+begin
+	RegRelative := False;
+	NeedFLine := False;
+	with Contents do begin
+		for I := 0 to Count - 1 do begin
+			L := Strings [I];
+			if L = #9'.set __relation,__ld_entry_point_plus_0x8000' then
+				RegRelative := True;
+			if Pos (FLineIdentifier, L) > 0 then
+				NeedFLine := True;
+			if RegRelative then begin
+				P1 := Pos ('-__relation', L);
+				while P1 > 0 do begin
+					P2 := PosEx ('_CALL_', L, P1, True);
+					if (P2 > 0) and (P2 < P1) and (P1 - P2 <= Length ('_CALL_') + 4) then begin
+						System.Delete (L, P1, Length ('-__relation') + 1);
+						while (Length (L) > 0) and (L [P1] <> ')') do
+							System.Delete (L, P1, 1);
+						System.Delete (L, P1, 1);
+						Strings [I] := L;
+					end;
+					P2 := PosEx ('_ER_CODE_', L, P1, True);
+					if (P2 > 0) and (P2 < P1) and (P1 - P2 <= Length ('_ER_CODE_') + 5) then begin
+						System.Delete (L, P1, Length ('-__relation') + 1);
+						while (Length (L) > 0) and (L [P1] <> ')') do
+							System.Delete (L, P1, 1);
+						System.Delete (L, P1, 1);
+						Strings [I] := L;
+					end;
+					P1 := PosEx ('-__relation', L, P1 + 1);
+				end;
+			end;
+			if (Copy (L, 1, Length (#9'jra _ER_CODE_')) = #9'jra _ER_CODE_') or (Copy (L, 1, Length (#9'jmp _ER_CODE_')) = #9'jmp _ER_CODE_') then begin
+				System.Delete (L, 1, Length (#9'jxx _ER_CODE_'));
+				if Length (L) <= 4 then
+					Strings [I] := #9'.word _A_LINE+' + L;
+			end else begin
+				Changed := True;
+				if (Copy (L, 1, Length (#9'jbsr')) = #9'jbsr') and (Pos ('_CALL_', L) > 0) then
+					System.Delete (L, 1 + Length (#9'j'), Length ('b'))
+				else if (Copy (L, 1, Length (#9'jra')) = #9'jra') and (Pos ('_CALL_', L) > 0) then begin
+					System.Delete (L, 1, Length (#9'jra'));
+					L := #9'jmp' + L;
+				end else if Copy (L, 1, Length (#9'move.l #__ld_calc_const_')) = #9'move.l #__ld_calc_const_' then
+					L [1 + Length (#9'move.')] := 'w'
+				else
+					Changed := False;
+				if NeedFLine and (Copy (L, 1, Length (#9'jsr _ROM_CALL_')) = #9'jsr _ROM_CALL_') then begin
+					System.Delete (L, 1, Length (#9'jsr _ROM_CALL_'));
+					if Length (L) <= 3 then
+						Strings [I] := #9'.word _F_LINE+0x' + L;
+				end else begin
+					P1 := Pos ('_ROM_CALL_', L);
+					while P1 > 0 do begin
+						P2 := P1;
+						Inc (P1, Length ('_ROM_CALL_'));
+						while (P1 <= Length (L)) and (L [P1] in ['0'..'9', 'a'..'z', 'A'..'Z', '_', '+', '-', '*', '/']) do
+							Inc (P1);
+						while (P1 <= Length (L)) and (L [P1] in [':', 'a'..'z', 'A'..'Z']) do
+							System.Delete (L, P1, 1);
+						System.Insert (':l', L, P1);
+						Inc (P1, Length (':l'));
+						if LowerCase (Copy (L, P1, Length ('(%pc)'))) = '(%pc)' then
+							System.Delete (L, P1, Length ('(%pc)'))
+						else if (LowerCase (Copy (L, P1, Length (',%pc)'))) = ',%pc)') and (P2 - 1 > 0) and (L [P2 - 1] = '(') then begin
+							System.Delete (L, P1, Length (',%pc)'));
+							System.Delete (L, P2 - 1, 1);
+						end;
+						Changed := True;
+						P1 := PosEx ('_ROM_CALL_', L, P1);
+					end;
+					P1 := Pos ('__ld_calc_const_', L);
+					while P1 > 0 do begin
+						P2 := P1;
+						Inc (P1, Length ('__ld_calc_const_'));
+						while (P1 <= Length (L)) and (L [P1] in ['0'..'9', 'a'..'z', 'A'..'Z', '_', ':']) do
+							Inc (P1);
+						if LowerCase (Copy (L, P1, Length ('(%pc)'))) = '(%pc)' then begin
+							System.Delete (L, P1, Length ('(%pc)'));
+							Changed := True;
+						end else if (LowerCase (Copy (L, P1, Length (',%pc)'))) = ',%pc)') and (P2 - 1 > 0) and (L [P2 - 1] = '(') then begin
+							System.Delete (L, P1, Length (',%pc)'));
+							System.Delete (L, P2 - 1, 1);
+							Changed := True;
+						end;
+						P1 := PosEx ('__ld_calc_const_', L, P1);
+					end;
+					if Changed then
+						Strings [I] := L;
+				end;
+			end;
+		end;
+	end;
+end;
+
+procedure ParseDebugSFile(Contents: TStringList; OnLineChange: TLineChangeEvent; LineContents: TStringList; OnGetLineContents: TLineContentsEvent);
+function GetLineContents(StartLine, EndLine: Integer): string;
+var
+	I: Integer;
+begin
+	if Assigned (OnGetLineContents) then
+		Result := OnGetLineContents (StartLine, EndLine)
+	else if Assigned (LineContents) then begin
+		Result := '';
+		for I := StartLine - 1 to EndLine - 1 do
+			if (I >= 0) and (I < LineContents.Count) then
+				Insert (LineContents.Strings [I] + #13#10, Result, Length (Result) + 1);
+		Delete (Result, Length (Result) - 1, 2);
+	end else
+		Result := '';
+end;
+var
+	I,
+	P,
+	LastLine,
+	RecontinueLine,
+	LastDebugLine,
+	CurDebugLine: Integer;
+	S: string;
+begin
+	LastLine := -1;
+	LastDebugLine := -1;
+	RecontinueLine := -1;
+	I := 0;
+	with Contents do
+		while I <= Count do begin
+			if (I < Count) and (Copy (Strings [I], 1, Length (#9'.def'#9)) = #9'.def'#9) then begin
+				Delete (I);
+				if Assigned (OnLineChange) then
+					OnLineChange (I, -1);
+				Dec (I);
+			end else if (I >= Count) or (Copy (Strings [I], 1, Length (#9'.ln'#9)) = #9'.ln'#9) then begin
+				if I < Count then begin
+					S := Strings [I];
+					System.Delete (S, 1, Length (#9'.ln'#9));
+					try
+						CurDebugLine := StrToInt (S);
+					except
+						CurDebugLine := LastDebugLine;
+					end;
+					System.Insert (LineIndicator, S, 1);
+					System.Insert (#9, S, Length (S) + 1);
+					Strings [I] := S;
+				end else
+					CurDebugLine := LastDebugLine + 1;
+				if (LastLine >= 0) and (CurDebugLine >= 0) then begin
+					S := Strings [LastLine];
+					if CurDebugLine < LastDebugLine then begin
+						System.Insert (StringReplace (Trim (GetLineContents (LastDebugLine, LastDebugLine)), #9, '', [rfReplaceAll]) + ' ...', S, Length (S) + 1);
+						RecontinueLine := LastDebugLine;
+					end else begin
+						if (RecontinueLine >= 0) and (CurDebugLine >= RecontinueLine) then begin
+							System.Insert (StringReplace (Trim (GetLineContents (LastDebugLine, LastDebugLine)) + ' ...', #9, '', [rfReplaceAll]), S, Length (S) + 1);
+							RecontinueLine := -1;
+						end else
+							System.Insert (StringReplace (Trim (GetLineContents (LastDebugLine, CurDebugLine - 1)), #9, '', [rfReplaceAll]), S, Length (S) + 1);
+					end;
+					repeat
+						P := Pos (#10, S);
+						if P <= 0 then
+							P := Pos (#13, S);
+						if P > 0 then
+							S [P] := ' ';
+					until P <= 0;
+					Strings [LastLine] := S;
+				end;
+				LastLine := I;
+				LastDebugLine := CurDebugLine;
+			end;
+			Inc (I);
+		end;
+end;
+
+procedure ParsePStarter(const InputFile: string; const OutputFile: string; const PackVar: string);
+const
+	TempProg = 'TEMPPROG';
+var
+	I: Integer;
+	ObjectFile: TMemoryStream;
+	Buf: PChar;
+	Len: Integer;
+	TempBuf: array [0..Length(TempProg)] of Char;
+begin
+	TempBuf [Length (TempProg)] := #0;
+	ObjectFile := TMemoryStream.Create;
+	try
+		ObjectFile.LoadFromFile (InputFile);
+		Buf := ObjectFile.Memory;
+		Len := ObjectFile.Size;
+		for I := 0 to Len - Length (TempProg) do
+			if UpCase (Buf [I]) = TempProg [1] then begin
+				Move (Buf [I], TempBuf, Length (TempProg));
+				if UpperCase (AnsiString (TempBuf)) = TempProg then begin
+					FillChar (Buf [I], Length (TempProg), 0);
+					StrPLCopy (PChar (@(Buf [I])), LowerCase (PackVar), Length (TempProg));
+					Break;
+				end;
+			end;
+		ObjectFile.SaveToFile (OutputFile);
+	finally
+		ObjectFile.Free;
+	end;
+end;
+
+procedure ParseDebugSFileDisk(Contents: TStringList; const SourceFileName: string);
+var
+	L: TStringList;
+begin
+	L := TStringList.Create;
+	with L do try
+		LoadFromFile (SourceFileName);
+		ParseDebugSFile (Contents, nil, L, nil);
+	finally
+		Free;
+	end;
+end;
+
+{ Functions to read integers machine-independently }
+
+function ReadCalcInt(Int: TCalcInt1): Byte;
+begin
+	Result := Int.Int;
+end;
+
+function ReadCalcInt(Int: TCalcInt2): Word;
+begin
+	Result := ReadCalcInt (Int.Hi) shl (SizeOf (Int.Lo) * 8) or ReadCalcInt (Int.Lo);
+end;
+
+function ReadCalcInt(Int: TCalcInt4): LongWord;
+begin
+	Result := ReadCalcInt (Int.Hi) shl (SizeOf (Int.Lo) * 8) or ReadCalcInt (Int.Lo);
+end;
+
+function ReadPCInt(Int: TPCInt1): Byte;
+begin
+	Result := Int.Int;
+end;
+
+function ReadPCInt(Int: TPCInt2): Word;
+begin
+	Result := ReadPCInt (Int.Hi) shl (SizeOf (Int.Lo) * 8) or ReadPCInt (Int.Lo);
+end;
+
+function ReadPCInt(Int: TPCInt4): LongWord;
+begin
+	Result := ReadPCInt (Int.Hi) shl (SizeOf (Int.Lo) * 8) or ReadPCInt (Int.Lo);
+end;
+
+{ Functions to write integers machine-independently }
+
+procedure WriteCalcInt(Input: Byte; out Int: TCalcInt1);
+begin
+	Int.Int := Input;
+end;
+
+procedure WriteCalcInt(Input: Word; out Int: TCalcInt2);
+begin
+	WriteCalcInt (Byte (Input shr (SizeOf (Int.Lo) * 8)), Int.Hi);
+	WriteCalcInt (Byte (Input), Int.Lo);
+end;
+
+procedure WriteCalcInt(Input: LongWord; out Int: TCalcInt4);
+begin
+	WriteCalcInt (Word (Input shr (SizeOf (Int.Lo) * 8)), Int.Hi);
+	WriteCalcInt (Word (Input), Int.Lo);
+end;
+
+procedure WritePCInt(Input: Byte; out Int: TPCInt1);
+begin
+	Int.Int := Input;
+end;
+
+procedure WritePCInt(Input: Word; out Int: TPCInt2);
+begin
+	WritePCInt (Byte (Input shr (SizeOf (Int.Lo) * 8)), Int.Hi);
+	WritePCInt (Byte (Input), Int.Lo);
+end;
+
+procedure WritePCInt(Input: LongWord; out Int: TPCInt4);
+begin
+	WritePCInt (Word (Input shr (SizeOf (Int.Lo) * 8)), Int.Hi);
+	WritePCInt (Word (Input), Int.Lo);
+end;
+
+{ Calculator file creation functions }
+
+function GetCalcVarSize(ContentLength: LongWord; const Extension: string = ''): LongWord;
+begin
+	Result := SizeOf (TCalcVarHeader) + ContentLength + SizeOf (TCalcVarFooter);
+	if Length (Extension) > 0 then
+		Inc (Result, Length (Extension) + 2);
+	if Result > MaxCalcAllocBlock then
+		Result := 0;
+end;
+
+function GetTransferFileSize(ContentLength: LongWord; const Extension: string = ''; OutputBin: Boolean = False): LongWord;
+begin
+	Result := GetCalcVarSize (ContentLength, Extension);
+	if (Result > 0) and (not OutputBin) then
+		Inc (Result, SizeOf (TTransferFileHeader) + SizeOf (TTransferFileFooter));
+end;
+
+procedure ProduceTransferFile(Output: Pointer; Contents: Pointer; ContentLength: LongWord; CalcDest: TCalcDest; const DestFolder, DestVarName: string; VarTag: Byte; const Extension: string = ''; OutputBin: Boolean = False);
+const
+	Res1: TTFRes2 = ($01, $00);
+	Res2: TTFRes6 = ($01, $00, $52, $00, $00, $00);
+	Res3: TTFRes3 = ($00, $00, $00);
+	Res4: TTFRes6 = ($A5, $5A, $00, $00, $00, $00);
+var
+	Size,
+	CalcSize: LongWord;
+	Header: PTransferFileHeader;
+	CalcHeader: PCalcVarHeader;
+	CalcFooter: PCalcVarFooter;
+	Footer: PTransferFileFooter;
+	Data: Pointer;
+	VarLinkType: Byte;
+	I,
+	Sum: Word;
+begin
+	CalcSize := GetCalcVarSize (ContentLength, Extension);
+	Size := GetTransferFileSize (ContentLength, Extension, OutputBin);
+	if Size > 0 then begin
+		FillChar (Output^, Size, 0);
+		if OutputBin then begin
+			CalcHeader := Output;
+			CalcFooter := Pointer (@(PBinData(Output) [Size - SizeOf (TCalcVarFooter)]));
+			Data := @(PBinData(Output) [SizeOf (TCalcVarHeader)]);
+		end else begin
+			CalcHeader := Pointer (@(PBinData(Output) [SizeOf (TTransferFileHeader)]));
+			CalcFooter := Pointer (@(PBinData(Output) [Size - SizeOf (TTransferFileFooter) - SizeOf (TCalcVarFooter)]));
+			Data := @(PBinData(Output) [SizeOf (TTransferFileHeader) + SizeOf (TCalcVarHeader)]);
+		end;
+		WriteCalcInt (CalcSize - SizeOf (TCalcInt2), CalcHeader.DataSize);
+		Move (Contents^, Data^, ContentLength);
+		if Length (Extension) > 0 then
+			StrPCopy (Pointer (@(PBinData(Data) [ContentLength + 1])), Extension);
+		WriteCalcInt (VarTag, CalcFooter.Tag);
+		if not OutputBin then begin
+			Header := Output;
+			Footer := Pointer (@(PBinData(Output) [Size - SizeOf (TTransferFileFooter)]));
+			with Header^ do begin
+				case CalcDest of
+					cdTI92:
+						Signature := '**TI92**';
+					cdTI89:
+						Signature := '**TI89**'
+					else
+						Signature := '**TI92P*';
+				end;
+				Reserved1 := Res1;
+				Reserved2 := Res2;
+				Reserved3 := Res3;
+				Reserved4 := Res4;
+				StrPLCopy (Folder, LowerCase (DestFolder), SizeOf (Folder));
+				StrPLCopy (VarName, LowerCase (DestVarName), SizeOf (VarName));
+				case VarTag of
+					$2D: VarLinkType := $0C;
+					$DC: VarLinkType := $12;
+					$F3: VarLinkType := $21;
+					$F8: VarLinkType := $1C;
+					else VarLinkType := 0;
+				end;
+				WritePCInt (VarLinkType, LinkType);
+				WritePCInt (Size, FileSize);
+			end;
+			Sum := 0;
+			for I := 0 to CalcSize - 1 do
+				Inc (Sum, Byte (PBinData(CalcHeader) [I]));
+			WritePCInt (Sum, Footer.CheckSum);
+		end;
+	end;
+end;
+
+function GetTransferFileExt(CalcDest: TCalcDest; VarTag: Byte; OutputBin: Boolean = False): string;
+var
+	TypeExt: Char;
+begin
+	case CalcDest of
+		cdTI92:
+			Result := '92';
+		cdTI89:
+			Result := '89';
+		cdTI92Plus:
+			Result := '9x';
+		cdV200:
+			Result := 'v2';
+		else
+			Result := 'xx';
+	end;
+	case VarTag of
+		$2D: TypeExt := 's';
+		$DC: TypeExt := 'p';
+		$F3: TypeExt := 'z';
+		else TypeExt := 'y';
+	end;
+	if OutputBin then
+		Result := '.' + TypeExt + Result
+	else
+		Result := '.' + Result + TypeExt;
+end;
+
+function GetOSUpgradeFileSize(ContentLength: LongWord; OutputBin: Boolean = True): LongWord;
+begin
+	Result := ContentLength + SizeOf (TCalcOSFooter);
+end;
+
+procedure ProduceOSUpgradeFile(Output: Pointer; Contents: Pointer; ContentLength: LongWord; OutputBin: Boolean = True);
+var
+	CalcFooter: PCalcOSFooter;
+begin
+	Move (Contents^, Output^, ContentLength);
+	CalcFooter := Pointer (@(PBinData(Output) [ContentLength]));
+	FillChar (CalcFooter^, SizeOf (TCalcOSFooter), 0);
+	with CalcFooter^ do begin
+		WriteCalcInt ($020D, SignatureHeader);
+		WriteCalcInt ($40,   SignatureType);
+	end;
+end;
+
+function GetOSUpgradeFileExt(CalcDest: TCalcDest; OutputBin: Boolean = False): string;
+begin
+	case CalcDest of
+		cdTI92:
+			Result := '92';
+		cdTI89:
+			Result := '89';
+		cdTI89Titanium:
+			Result := '89ti';
+		cdTI92Plus:
+			Result := '9x';
+		cdV200:
+			Result := 'v2';
+		else
+			Result := 'xx';
+	end;
+	Result := '-' + Result + '.tib';
+end;
+
+end.

BIN
tigcc/ide/PreferencesUnit.dfm


+ 491 - 0
tigcc/ide/PreferencesUnit.pas

@@ -0,0 +1,491 @@
+unit PreferencesUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, ExtCtrls, ComCtrls, SourceEditUnit{$IFDEF CODINGEXT}, PrefFrame{$ENDIF};
+
+type
+  TPreferencesForm = class(TForm)
+    OKButton: TButton;
+    CancelButton: TButton;
+		ColorDlg: TColorDialog;
+    FontDlg: TFontDialog;
+    PageController: TPageControl;
+		GeneralSheet: TTabSheet;
+    StopCompilationBox: TCheckBox;
+		FlatButtonsCheckBox: TCheckBox;
+    MenuBitmapsCheckBox: TCheckBox;
+    AutoSaveCheckBox: TCheckBox;
+    EditorSheet: TTabSheet;
+		Label2: TLabel;
+		CTabSizeEdit: TEdit;
+    ColorCheckBox: TCheckBox;
+    ChangeColorButton: TButton;
+		Label3: TLabel;
+		ChangeFontButton: TButton;
+    FontLabel: TPanel;
+    SyntaxHighlightingSheet: TTabSheet;
+    Label4: TLabel;
+		ASMTabSizeEdit: TEdit;
+    LanguageSelectionBox: TComboBox;
+    Label5: TLabel;
+    SyntaxEnabledBox: TCheckBox;
+		Button1: TButton;
+    Button2: TButton;
+    Button3: TButton;
+    Button4: TButton;
+    Button5: TButton;
+		Button6: TButton;
+    ObjectTree: TTreeView;
+    Button7: TButton;
+    Button8: TButton;
+    Button9: TButton;
+    OKTimer: TTimer;
+		OpenFolderBox: TCheckBox;
+		DeleteObjectFilesBox: TCheckBox;
+    ResetButton: TButton;
+    OnFlyCheckBox: TCheckBox;
+    DeleteErrorsCheckBox: TCheckBox;
+    AutoBlockCheckBox: TCheckBox;
+    SplitFilesCheckBox: TCheckBox;
+    DeleteAssemblyFilesBox: TCheckBox;
+    AllowImplicitCheckBox: TCheckBox;
+    AutoNewsCheckBox: TCheckBox;
+    TransferSheet: TTabSheet;
+    TargetBox: TGroupBox;
+    VTIBox: TRadioButton;
+    RealCalcBox: TRadioButton;
+    PortBox: TGroupBox;
+    PortCOM1Box: TRadioButton;
+    PortCOM2Box: TRadioButton;
+    PortCOM3Box: TRadioButton;
+    PortCOM4Box: TRadioButton;
+    CableBox: TGroupBox;
+    CableBlackBox: TRadioButton;
+    CableGrayBox: TRadioButton;
+    NoneBox: TRadioButton;
+    VTIPathEdit: TEdit;
+    VTIPathBrowseButton: TButton;
+    BrowseDlg: TOpenDialog;
+    DragDropEditCheckBox: TCheckBox;
+    RemoveTrailingSpcCheckBox: TCheckBox;
+    JumpToErrorBox: TCheckBox;
+		procedure ColorCheckBoxClick(Sender: TObject);
+		procedure ChangeColorButtonClick(Sender: TObject);
+		procedure ChangeFontButtonClick(Sender: TObject);
+		procedure FormCreate(Sender: TObject);
+		procedure FormDestroy(Sender: TObject);
+		procedure FormShow(Sender: TObject);
+		procedure LanguageSelectionBoxChange(Sender: TObject);
+		procedure ObjectTreeChange(Sender: TObject; Node: TTreeNode);
+		procedure SyntaxEnabledBoxClick(Sender: TObject);
+    procedure Button1Click(Sender: TObject);
+		procedure Button3Click(Sender: TObject);
+    procedure Button2Click(Sender: TObject);
+    procedure Button4Click(Sender: TObject);
+    procedure Button6Click(Sender: TObject);
+    procedure Button5Click(Sender: TObject);
+    procedure ObjectTreeKeyDown(Sender: TObject; var Key: Word;
+      Shift: TShiftState);
+		procedure EditItem(Sender: TObject);
+		procedure Button7Click(Sender: TObject);
+    procedure Button8Click(Sender: TObject);
+    procedure ObjectTreeEdited(Sender: TObject; Node: TTreeNode;
+			var S: String);
+		procedure ObjectTreeEditing(Sender: TObject; Node: TTreeNode;
+			var AllowEdit: Boolean);
+		procedure OKTimerTimer(Sender: TObject);
+		procedure ResetButtonClick(Sender: TObject);
+		procedure PageControllerChange(Sender: TObject);
+    procedure TargetBoxClick(Sender: TObject);
+    procedure VTIPathBrowseButtonClick(Sender: TObject);
+	private
+	public
+		BackColor: TColor;
+		EditorFont: TFont;
+		SyntaxC: TSyntaxColoring;
+		SyntaxAsmGNU: TSyntaxColoring;
+		SyntaxAsm: TSyntaxColoring;
+		SyntaxQuill: TSyntaxColoring;
+		Syntax: TSyntaxColoring;
+		SyntaxTabClicked: Boolean;
+
+{$IFDEF CODINGEXT}
+    procedure InitCodingExt;
+{$ENDIF}
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	MasterUnit,
+	UtilsDos, UtilsWin,
+	MainUnit, StyleSelectionUnit, ColorsUnit, CustomStyleUnit, WordListUnit;
+
+procedure TPreferencesForm.ColorCheckBoxClick(Sender: TObject);
+begin
+	ChangeColorButton.Enabled := ColorCheckBox.Checked;
+end;
+
+procedure TPreferencesForm.ChangeColorButtonClick(Sender: TObject);
+begin
+	with ColorDlg do begin
+		Color := BackColor;
+		if Execute then
+			BackColor := Color;
+	end;
+end;
+
+procedure TPreferencesForm.ChangeFontButtonClick(Sender: TObject);
+begin
+	with FontDlg do begin
+		Font.Assign (EditorFont);
+		if Execute then begin
+			EditorFont.Assign (Font);
+			FontLabel.Caption := EditorFont.Name;
+			FontLabel.Font.Assign (EditorFont);
+		end;
+	end;
+end;
+
+procedure TPreferencesForm.FormCreate(Sender: TObject);
+begin
+	EditorFont := TFont.Create;
+	SyntaxC := TSyntaxColoring.Create (nil);
+	SyntaxAsm := TSyntaxColoring.Create (nil);
+	SyntaxAsmGNU := TSyntaxColoring.Create (nil);
+	SyntaxQuill := TSyntaxColoring.Create (nil);
+	if ssA68k in SpecialSupport then
+		LanguageSelectionBox.Items.Add ('A68k ASM Files');
+	if ssQuill in SpecialSupport then
+		LanguageSelectionBox.Items.Add ('Quill Files');
+	LanguageSelectionBox.ItemIndex := 0;
+
+{$IFDEF CODINGEXT}
+  InitCodingExt;
+{$ENDIF}
+end;
+
+procedure TPreferencesForm.FormDestroy(Sender: TObject);
+begin
+	SyntaxQuill.Free;
+	SyntaxAsmGNU.Free;
+	SyntaxAsm.Free;
+	SyntaxC.Free;
+	EditorFont.Free;
+end;
+
+procedure TPreferencesForm.FormShow(Sender: TObject);
+begin
+	SyntaxTabClicked := PageController.ActivePage = SyntaxHighlightingSheet;
+	TargetBoxClick (Sender);
+	ColorCheckBoxClick (Sender);
+	FontLabel.Caption := EditorFont.Name;
+	FontLabel.Font.Assign (EditorFont);
+	LanguageSelectionBoxChange (Sender);
+end;
+
+procedure TPreferencesForm.LanguageSelectionBoxChange(Sender: TObject);
+label
+	Done;
+var
+	I: Integer;
+begin
+	I := LanguageSelectionBox.ItemIndex;
+	if I <= 0 then begin
+		Syntax := SyntaxC;
+		goto Done;
+	end;
+	Dec (I);
+	if I <= 0 then begin
+		Syntax := SyntaxAsmGNU;
+		goto Done;
+	end;
+	if ssA68k in SpecialSupport then begin
+		Dec (I);
+		if I <= 0 then begin
+			Syntax := SyntaxAsm;
+			goto Done;
+		end;
+	end;
+	if ssQuill in SpecialSupport then begin
+		Dec (I);
+		if I <= 0 then begin
+			Syntax := SyntaxQuill;
+			goto Done;
+		end;
+	end;
+	Done:
+	SyntaxEnabledBox.Checked := Syntax.Enabled;
+	SyntaxEnabledBoxClick (Sender);
+	ObjectTree.Items.BeginUpdate;
+	with ObjectTree.Items [0] do begin
+		Item[0].DeleteChildren;
+		Item[1].DeleteChildren;
+	end;
+	with Syntax do begin
+		with CustomStyles do
+			for I := 0 to Count - 1 do
+				ObjectTree.Items.AddChildObject (ObjectTree.Items[0].Item[0], Items[I].Caption, Pointer (Items [I]));
+		with WordLists do
+			for I := 0 to Count - 1 do
+				ObjectTree.Items.AddChildObject (ObjectTree.Items[0].Item[1], Items[I].Caption, Pointer (Items [I]));
+	end;
+	ObjectTree.FullExpand;
+	ObjectTree.Items.EndUpdate;
+	ObjectTreeChange (Sender, nil);
+end;
+
+procedure TPreferencesForm.ObjectTreeChange(Sender: TObject;
+	Node: TTreeNode);
+begin
+	Button9.Enabled := SyntaxEnabledBox.Checked and Assigned (ObjectTree.Selected) and Assigned (ObjectTree.Selected.Data);
+end;
+
+procedure TPreferencesForm.SyntaxEnabledBoxClick(Sender: TObject);
+begin
+	Syntax.Enabled := SyntaxEnabledBox.Checked;
+	Button1.Enabled := SyntaxEnabledBox.Checked;
+	Button2.Enabled := SyntaxEnabledBox.Checked;
+	Button3.Enabled := SyntaxEnabledBox.Checked;
+	Button4.Enabled := SyntaxEnabledBox.Checked;
+	Button5.Enabled := SyntaxEnabledBox.Checked;
+	Button6.Enabled := SyntaxEnabledBox.Checked;
+	Button7.Enabled := SyntaxEnabledBox.Checked;
+	Button8.Enabled := SyntaxEnabledBox.Checked;
+	ObjectTree.Enabled := SyntaxEnabledBox.Checked;
+	ObjectTreeChange (Sender, nil);
+end;
+
+procedure TPreferencesForm.Button1Click(Sender: TObject);
+begin
+	ColorDlg.Color := Syntax.NumberColor;
+	if ColorDlg.Execute then
+		Syntax.NumberColor := ColorDlg.Color;
+end;
+
+procedure TPreferencesForm.Button3Click(Sender: TObject);
+begin
+	ColorDlg.Color := Syntax.SymbolColor;
+	if ColorDlg.Execute then
+		Syntax.SymbolColor := ColorDlg.Color;
+end;
+
+procedure TPreferencesForm.Button2Click(Sender: TObject);
+begin
+	with TStyleSelectionForm.Create (Self) do try
+		CustomStyle := Syntax.NumberCustomStyle;
+		Style := Syntax.NumberStyle;
+		if ShowModal = mrOK then begin
+			Syntax.NumberCustomStyle := CustomStyle;
+			Syntax.NumberStyle := Style;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TPreferencesForm.Button4Click(Sender: TObject);
+begin
+	with TStyleSelectionForm.Create (Self) do try
+		CustomStyle := Syntax.SymbolCustomStyle;
+		Style := Syntax.SymbolStyle;
+		if ShowModal = mrOK then begin
+			Syntax.SymbolCustomStyle := CustomStyle;
+			Syntax.SymbolStyle := Style;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TPreferencesForm.Button6Click(Sender: TObject);
+begin
+	with TStyleSelectionForm.Create (Self) do try
+		CustomStyle := Syntax.ParenthesisCustomStyle;
+		Style := Syntax.ParenthesisStyle;
+		if ShowModal = mrOK then begin
+			Syntax.ParenthesisCustomStyle := CustomStyle;
+			Syntax.ParenthesisStyle := Style;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TPreferencesForm.Button5Click(Sender: TObject);
+begin
+	with TMultipleColorsForm.Create (Self) do try
+		ColorBox.Items.Assign (Syntax.ParenthesisColors);
+		if ShowModal = mrOK then
+			Syntax.ParenthesisColors.Assign (ColorBox.Items);
+	finally
+		Free;
+	end;
+end;
+
+procedure TPreferencesForm.ObjectTreeKeyDown(Sender: TObject;
+	var Key: Word; Shift: TShiftState);
+var
+	ItemData: TCollectionItem;
+begin
+	if Key = vk_Delete then begin
+		if Assigned (ObjectTree.Selected) and Assigned (ObjectTree.Selected.Data) then begin
+			ItemData := TCollectionItem (ObjectTree.Selected.Data);
+			ObjectTree.Selected.Delete;
+			ItemData.Free;
+		end;
+	end;
+end;
+
+procedure TPreferencesForm.EditItem(Sender: TObject);
+var
+	ItemData: TCollectionItem;
+begin
+	if Assigned (ObjectTree.Selected) and Assigned (ObjectTree.Selected.Data) then begin
+		ItemData := TCollectionItem (ObjectTree.Selected.Data);
+		if ItemData is TCustomStyle then
+			with TCustomStyleForm.Create (Self) do try
+				Style.Assign (ItemData);
+				if ShowModal = mrOK then
+					ItemData.Assign (Style);
+			finally
+				Free;
+			end
+		else if ItemData is TWordList then
+			with TWordListForm.Create (Self) do try
+				List.Assign (ItemData);
+				if ShowModal = mrOK then
+					ItemData.Assign (List);
+			finally
+				Free;
+			end;
+	end;
+end;
+
+procedure TPreferencesForm.Button7Click(Sender: TObject);
+var
+	ItemData: TCustomStyle;
+begin
+	if ObjectTree.Enabled then
+		ObjectTree.SetFocus;
+	ItemData := Syntax.CustomStyles.Add;
+	ItemData.Caption := 'New Style';
+	with ObjectTree.Items.AddChildObject (ObjectTree.Items[0].Item[0], ItemData.Caption, Pointer (ItemData)) do begin
+		MakeVisible;
+		EditText;
+	end;
+end;
+
+procedure TPreferencesForm.Button8Click(Sender: TObject);
+var
+	ItemData: TWordList;
+begin
+	if ObjectTree.Enabled then
+		ObjectTree.SetFocus;
+	ItemData := Syntax.WordLists.Add;
+	ItemData.Caption := 'New List';
+	with ObjectTree.Items.AddChildObject (ObjectTree.Items[0].Item[1], ItemData.Caption, Pointer (ItemData)) do begin
+		MakeVisible;
+		EditText;
+	end;
+end;
+
+procedure TPreferencesForm.ObjectTreeEdited(Sender: TObject;
+	Node: TTreeNode; var S: String);
+var
+	ItemData: TCollectionItem;
+begin
+	OKButton.Enabled := True;
+	if Assigned (Node.Data) then begin
+		ItemData := TCollectionItem (Node.Data);
+		if ItemData is TCustomStyle then
+			TCustomStyle(ItemData).Caption := S;
+		if ItemData is TWordList then
+			TWordList(ItemData).Caption := S;
+	end;
+	ObjectTree.Selected := Node;
+end;
+
+procedure TPreferencesForm.ObjectTreeEditing(Sender: TObject;
+	Node: TTreeNode; var AllowEdit: Boolean);
+begin
+	AllowEdit := Assigned (Node.Data);
+	if AllowEdit then begin
+		OKButton.Enabled := False;
+		OKTimer.Enabled := True;
+	end;
+end;
+
+procedure TPreferencesForm.OKTimerTimer(Sender: TObject);
+begin
+	if not ObjectTree.IsEditing then begin
+		OKButton.Enabled := True;
+		OKTimer.Enabled := False;
+	end;
+end;
+
+procedure TPreferencesForm.ResetButtonClick(Sender: TObject);
+begin
+	if Syntax = SyntaxC then
+		Syntax.Assign (MainForm.SyntaxCBackup)
+	else if Syntax = SyntaxAsmGNU then
+		Syntax.Assign (MainForm.SyntaxAsmGNUBackup)
+	else if Syntax = SyntaxAsm then
+		Syntax.Assign (MainForm.SyntaxAsmBackup)
+	else if Syntax = SyntaxQuill then
+		Syntax.Assign (MainForm.SyntaxQuillBackup);
+	LanguageSelectionBoxChange (Sender);
+end;
+
+procedure TPreferencesForm.PageControllerChange(Sender: TObject);
+begin
+	if PageController.ActivePage = SyntaxHighlightingSheet then
+		SyntaxTabClicked := True;
+end;
+
+procedure TPreferencesForm.TargetBoxClick(Sender: TObject);
+begin
+	VTIPathEdit.Enabled := VTIBox.Checked;
+	VTIPathBrowseButton.Enabled := VTIPathEdit.Enabled;
+	PortBox.Enabled := RealCalcBox.Checked;
+	PortCOM1Box.Enabled := PortBox.Enabled;
+	PortCOM2Box.Enabled := PortBox.Enabled;
+	PortCOM3Box.Enabled := PortBox.Enabled;
+	PortCOM4Box.Enabled := PortBox.Enabled;
+	CableBox.Enabled := PortBox.Enabled;
+	CableBlackBox.Enabled := CableBox.Enabled;
+	CableGrayBox.Enabled := CableBox.Enabled;
+end;
+
+procedure TPreferencesForm.VTIPathBrowseButtonClick(Sender: TObject);
+begin
+	with BrowseDlg do begin
+		FileName := VTIPathEdit.Text;
+		if Execute then
+			VTIPathEdit.Text := FileName;
+	end;
+end;
+
+{$IFDEF CODINGEXT}
+procedure TPreferencesForm.InitCodingExt;
+var
+  Tab: TTabSheet;
+  Frame: TCodingExt;
+begin
+  Tab := TTabSheet.Create(Self);
+  Tab.PageControl := PageController;
+  Tab.Caption := 'Coding';
+
+  Frame := TCodingExt.Create(Self);
+  Frame.Parent := Tab;
+  Tab.OnShow := Frame.OnShow;
+end;
+{$ENDIF}
+
+end.
+

+ 281 - 0
tigcc/ide/ProcessUnit.pas

@@ -0,0 +1,281 @@
+unit ProcessUnit;
+
+interface
+
+uses
+	HandleWaitThreadUnit, FileReadToBufferThreadUnit,
+	Windows, Classes;
+
+type
+	TRedirect = class;
+
+	TProcessConsole = class(TObject)
+	private
+		FTitle: string;
+		FProcessInfo: TProcessInformation;
+		FStdOut: TRedirect;
+		FStdErr: TRedirect;
+		FWaitThread: THandleWaitThread;
+		FPriorityClass: DWord;
+		function GetLastOutText: string;
+		function GetLastErrText: string;
+		function GetRunning: Boolean;
+    function GetLastErrSize: Integer;
+    function GetLastOutSize: Integer;
+	protected
+		property StdOut: TRedirect read FStdOut;
+		property StdErr: TRedirect read FStdErr;
+		property ProcessInfo: TProcessInformation read FProcessInfo;
+		property WaitThread: THandleWaitThread read FWaitThread;
+	public
+		constructor Create;
+		destructor Destroy; override;
+		procedure StartProcess(const ProgramFile, Parameters, HomeDir: string);
+		procedure KillProcess;
+		procedure KillProcessAndWait;
+		procedure WaitForTermination;
+		property Running: Boolean read GetRunning;
+		property LastOutText: string read GetLastOutText;
+		property LastErrText: string read GetLastErrText;
+		property LastOutSize: Integer read GetLastOutSize;
+		property LastErrSize: Integer read GetLastErrSize;
+	published
+		property Title: string read FTitle write FTitle;
+		property PriorityClass: DWord read FPriorityClass write FPriorityClass;
+	end;
+
+	TRedirect = class(TObject)
+	private
+		FProgramOutputHandle: HFile;
+		FPipe: HFile;
+		FThread: TFileReadToBufferThread;
+		FStream: TMemoryStream;
+		FFinish: Boolean;
+		function GetText: string;
+		function GetOutputSize: Integer;
+	public
+		constructor Create;
+		destructor Destroy; override;
+		procedure Clear;
+		procedure Finish;
+		property Stream: TMemoryStream read FStream;
+		property Thread: TFileReadToBufferThread read FThread;
+		property Pipe: HFile read FPipe;
+		property ProgramOutputHandle: HFile read FProgramOutputHandle;
+		property Text: string read GetText;
+		property OutputSize: Integer read GetOutputSize;
+	end;
+
+implementation
+
+uses
+	SysUtils, UtilsWin;
+
+{ TProcessConsole }
+
+constructor TProcessConsole.Create;
+begin
+	inherited;
+	FStdOut := TRedirect.Create;
+	FStdErr := TRedirect.Create;
+	Title := 'Console';
+	PriorityClass := HIGH_PRIORITY_CLASS;
+end;
+
+destructor TProcessConsole.Destroy;
+begin
+	KillProcessAndWait;
+	FStdErr.Free;
+	FStdOut.Free;
+	inherited;
+end;
+
+function TProcessConsole.GetLastErrSize: Integer;
+begin
+	Result := StdErr.OutputSize;
+end;
+
+function TProcessConsole.GetLastErrText: string;
+begin
+	Result := StdErr.Text;
+end;
+
+function TProcessConsole.GetLastOutSize: Integer;
+begin
+	Result := StdOut.OutputSize;
+end;
+
+function TProcessConsole.GetLastOutText: string;
+begin
+	Result := StdOut.Text;
+end;
+
+function TProcessConsole.GetRunning: Boolean;
+var
+	T: TThread;
+begin
+	if Assigned (WaitThread) then begin
+		Result := not WaitThread.HasTerminated;
+		if not Result then begin
+			T := FWaitThread;
+			FWaitThread := nil;
+			T.Free;
+			with FProcessInfo do begin
+				CloseHandle (hProcess);
+				CloseHandle (hThread);
+				hProcess := 0;
+				hThread := 0;
+			end;
+			StdOut.Finish;
+			StdErr.Finish;
+		end;
+	end else
+		Result := False;
+end;
+
+procedure TProcessConsole.KillProcess;
+begin
+	if Running then begin
+		TerminateProcess (ProcessInfo.hProcess, 1);
+		if Assigned (WaitThread) then
+			WaitThread.Terminate;
+	end;
+end;
+
+procedure TProcessConsole.KillProcessAndWait;
+begin
+	KillProcess;
+	WaitForTermination;
+end;
+
+procedure TProcessConsole.StartProcess(const ProgramFile, Parameters, HomeDir: string);
+var
+	StartupInfo: TStartupInfo;
+	CommandLine: string;
+	HomeDirPC: PChar;
+begin
+	if Running then
+		raise EFOpenError.Create ('Another process is still running')
+	else begin
+		StdOut.Clear;
+		StdErr.Clear;
+		FillChar (StartupInfo, SizeOf (StartupInfo), 0);
+		with StartupInfo do begin
+			cb := SizeOf (StartupInfo);
+			lpTitle := PChar (Title);
+			wShowWindow := sw_Hide;
+			hStdOutput := StdOut.ProgramOutputHandle;
+			hStdError := StdErr.ProgramOutputHandle;
+			dwFlags := StartF_UseShowWindow or StartF_UseStdHandles;
+		end;
+		if Length (ProgramFile) > 0 then
+			CommandLine := '"' + ProgramFile + '" ' + Parameters
+		else
+			CommandLine := Parameters;
+		if Length (HomeDir) > 0 then
+			HomeDirPC := PChar (HomeDir)
+		else
+			HomeDirPC := nil;
+		if CreateProcess (nil, PChar (CommandLine), nil, nil, True, PriorityClass, nil, HomeDirPC, StartupInfo, FProcessInfo) then begin
+			FWaitThread := THandleWaitThread.Create (ProcessInfo.hProcess);
+		end else
+			raise EFOpenError.Create ('Could not start process');
+	end;
+end;
+
+procedure TProcessConsole.WaitForTermination;
+begin
+	if Assigned (WaitThread) then
+		WaitThread.WaitFor;
+end;
+
+{ TRedirect }
+
+procedure TRedirect.Clear;
+begin
+	FFinish := False;
+	Thread.Lock.BeginWrite;
+	Stream.Clear;
+	Thread.Lock.EndWrite;
+end;
+
+constructor TRedirect.Create;
+var
+	Attr: TSecurityAttributes;
+	TempPipe: HFile;
+begin
+	inherited;
+	FillChar (Attr, SizeOf (Attr), 0);
+	with Attr do begin
+		nLength := SizeOf (Attr);
+		lpSecurityDescriptor := nil;
+		bInheritHandle := True;
+	end;
+	CreatePipe (TempPipe, FProgramOutputHandle, @Attr, 0);
+	DuplicateHandle (GetCurrentProcess, TempPipe, GetCurrentProcess, @FPipe, 0, False, Duplicate_Close_Source or Duplicate_Same_Access);
+	FStream := TMemoryStream.Create;
+	FThread := TFileReadToBufferThread.Create (Pipe, Stream);
+end;
+
+destructor TRedirect.Destroy;
+begin
+	if Assigned (Thread) then
+		Thread.Terminate;
+	Finish;
+	CloseHandle (FProgramOutputHandle);
+	if Assigned (Thread) then begin
+		Thread.WaitFor;
+		FThread.Free;
+	end;
+	if Assigned (Stream) then
+		FStream.Free;
+	CloseHandle (FPipe);
+	inherited;
+end;
+
+procedure TRedirect.Finish;
+const
+	B: Byte = 0;
+var
+	BW: Cardinal;
+begin
+	if not FFinish then begin
+		FFinish := True;
+		WriteFile (ProgramOutputHandle, B, 1, BW, nil);
+	end;
+end;
+
+function TRedirect.GetOutputSize: Integer;
+begin
+	Thread.Lock.BeginRead;
+	Result := Stream.Size;
+	Thread.Lock.EndRead;
+end;
+
+function TRedirect.GetText: string;
+var
+	Finished: Boolean;
+begin
+	if FFinish then begin
+		repeat
+			Thread.Lock.BeginRead;
+			with Stream do
+				Finished := (Size > 0) and (PChar(Memory) [Size - 1] = #0);
+			Thread.Lock.EndRead;
+			if not Finished then
+				Sleep (100);
+		until Finished;
+		Result := AnsiString (PChar (Stream.Memory));
+	end else begin
+		Thread.Lock.BeginWrite;
+		with Stream do begin
+			Size := Size + 1;
+			PChar(Memory) [Size - 1] := #0;
+			Result := AnsiString (PChar (Memory));
+			Size := Size - 1;
+		end;
+		Thread.Lock.EndWrite;
+	end;
+end;
+
+end.

BIN
tigcc/ide/ProgramOptionsUnit.dfm


+ 202 - 0
tigcc/ide/ProgramOptionsUnit.pas

@@ -0,0 +1,202 @@
+unit ProgramOptionsUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ExtCtrls, ComCtrls;
+
+type
+	TProgramOptionsForm = class(TForm)
+    CloseButton: TButton;
+		PageController: TPageControl;
+		CalculatorSheet: TTabSheet;
+    Label2: TLabel;
+		TI89CheckBox: TCheckBox;
+		TI92PlusCheckBox: TCheckBox;
+    V200CheckBox: TCheckBox;
+    Label5: TLabel;
+    OSSheet: TTabSheet;
+		Label3: TLabel;
+    NoStubRadioButton: TRadioButton;
+    DoorsRadioButton: TRadioButton;
+    PreOSRadioButton: TRadioButton;
+    MinAMSCheckBox: TCheckBox;
+    MinAMSEdit: TEdit;
+		RelocFormatSheet: TTabSheet;
+		Panel2: TPanel;
+    Label4: TLabel;
+    RelocAMSRadioButton: TRadioButton;
+		RelocKernelRadioButton: TRadioButton;
+		RelocCompressedRadioButton: TRadioButton;
+    Panel3: TPanel;
+    Label15: TLabel;
+    ROMCallDirectRadioButton: TRadioButton;
+		ROMCallKernelRadioButton: TRadioButton;
+		ROMCallCompressedRadioButton: TRadioButton;
+    ROMCallFLineRadioButton: TRadioButton;
+    InternalFLineEmulatorCheckBox: TCheckBox;
+		BSSFormatSheet: TTabSheet;
+		HomeScreenSheet: TTabSheet;
+		LCDSaveCheckBox: TCheckBox;
+		EnableErrorReturnCheckBox: TCheckBox;
+		Label11: TLabel;
+		ReturnValueRadioButton: TRadioButton;
+		ReturnDoneRadioButton: TRadioButton;
+		Label10: TLabel;
+		Label7: TLabel;
+    Panel1: TPanel;
+		Label6: TLabel;
+    BSSKernelRadioButton: TRadioButton;
+    BSSCompressedRadioButton: TRadioButton;
+    BSSMergeRadioButton: TRadioButton;
+    Panel4: TPanel;
+    Label8: TLabel;
+		DataVarKernelRadioButton: TRadioButton;
+		DataVarCompressedRadioButton: TRadioButton;
+		WelcomeSheet: TTabSheet;
+		Label1: TLabel;
+		Label9: TLabel;
+		OptimizeCalcConstsCheckBox: TCheckBox;
+		Label12: TLabel;
+		RelocFLineJumpsCheckBox: TCheckBox;
+		UnofficialOSSupportCheckBox: TCheckBox;
+		RelocFLineJumps4ByteCheckBox: TCheckBox;
+    ROMCallOptimizedCheckBox: TCheckBox;
+		procedure FormShow(Sender: TObject);
+		procedure ShellRadioButtonClick(Sender: TObject);
+		procedure MinAMSCheckBoxClick(Sender: TObject);
+		procedure RelocRadioButtonClick(Sender: TObject);
+		procedure ItemMouseDown(Sender: TObject; Button: TMouseButton;
+			Shift: TShiftState; X, Y: Integer);
+		procedure CalcCheckBoxClick(Sender: TObject);
+		procedure RelocFLineJumpsCheckBoxClick(Sender: TObject);
+	private
+	public
+	end;
+
+implementation
+
+uses
+	MainUnit;
+
+{$R *.DFM}
+
+procedure TProgramOptionsForm.FormShow(Sender: TObject);
+begin
+	ActiveControl := PageController;
+	CalcCheckBoxClick            (Sender);
+	ShellRadioButtonClick        (Sender);
+	MinAMSCheckBoxClick          (Sender);
+	RelocRadioButtonClick        (Sender);
+	RelocFLineJumpsCheckBoxClick (Sender);
+end;
+
+procedure TProgramOptionsForm.ShellRadioButtonClick(Sender: TObject);
+begin
+	with LCDSaveCheckBox do begin
+		Enabled := NostubRadioButton.Checked;
+		if not Enabled then
+			Checked := True;
+	end;
+	with RelocAMSRadioButton do begin
+		Enabled := NostubRadioButton.Checked;
+		if Checked and not Enabled then
+			RelocKernelRadioButton.Checked := True;
+	end;
+	with RelocKernelRadioButton do begin
+		Enabled := not PreOSRadioButton.Checked;
+		if Checked and not Enabled then
+			RelocCompressedRadioButton.Checked := True;
+	end;
+	with RelocCompressedRadioButton do begin
+		Enabled := not DoorsRadioButton.Checked;
+		if Checked and not Enabled then
+			RelocKernelRadioButton.Checked := True;
+	end;
+	with ROMCallDirectRadioButton do begin
+		Enabled := NostubRadioButton.Checked;
+		if Checked and not Enabled then
+			ROMCallKernelRadioButton.Checked := True;
+	end;
+	with ROMCallKernelRadioButton do begin
+		Enabled := not PreOSRadioButton.Checked;
+		if Checked and not Enabled then
+			ROMCallCompressedRadioButton.Checked := True;
+	end;
+	with ROMCallCompressedRadioButton do begin
+		Enabled := not DoorsRadioButton.Checked;
+		if Checked and not Enabled then
+			ROMCallKernelRadioButton.Checked := True;
+	end;
+	with BSSKernelRadioButton do begin
+		Enabled := not PreOSRadioButton.Checked;
+		if Checked and not Enabled then
+			BSSCompressedRadioButton.Checked := True;
+	end;
+	with BSSCompressedRadioButton do begin
+		Enabled := not DoorsRadioButton.Checked;
+		if Checked and not Enabled then
+			BSSKernelRadioButton.Checked := True;
+	end;
+	RelocRadioButtonClick (Sender);
+end;
+
+procedure TProgramOptionsForm.MinAMSCheckBoxClick(Sender: TObject);
+begin
+	MinAMSEdit.Enabled := MinAMSCheckBox.Checked;
+end;
+
+procedure TProgramOptionsForm.RelocRadioButtonClick(Sender: TObject);
+begin
+	with InternalFLineEmulatorCheckBox do begin
+		Enabled := (RelocFLineJumpsCheckBox.Checked or ROMCallFLineRadioButton.Checked) and (not RelocFLineJumps4ByteCheckBox.Checked);
+		if not Enabled then
+			Checked := RelocFLineJumps4ByteCheckBox.Checked;
+	end;
+	with ROMCallOptimizedCheckBox do begin
+		Enabled := (ROMCallDirectRadioButton.Checked or ROMCallFLineRadioButton.Checked) and NostubRadioButton.Checked;
+		if not Enabled then
+			Checked := False;
+	end;
+end;
+
+procedure TProgramOptionsForm.ItemMouseDown(Sender: TObject;
+	Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+begin
+	if Button = mbRight then
+		if Sender is TControl then
+			with TControl (Sender) do
+				MainForm.DocFile.KeywordLookup (Hint);
+end;
+
+procedure TProgramOptionsForm.CalcCheckBoxClick(Sender: TObject);
+var
+	CalcCount: Integer;
+begin
+	CalcCount := 0;
+	if TI89CheckBox.Checked then
+		Inc (CalcCount);
+	if TI92PlusCheckBox.Checked then
+		Inc (CalcCount);
+	if V200CheckBox.Checked then
+		Inc (CalcCount);
+	with OptimizeCalcConstsCheckBox do begin
+		Enabled := CalcCount > 1;
+		if not Enabled then
+			Checked := CalcCount = 1;
+	end;
+end;
+
+procedure TProgramOptionsForm.RelocFLineJumpsCheckBoxClick(
+	Sender: TObject);
+begin
+	with RelocFLineJumps4ByteCheckBox do begin
+		Enabled := RelocFLineJumpsCheckBox.Checked;
+		if not Enabled then
+			Checked := False;
+	end;
+	RelocRadioButtonClick (Sender);
+end;
+
+end.

BIN
tigcc/ide/ProgramOutputUnit.dfm


+ 33 - 0
tigcc/ide/ProgramOutputUnit.pas

@@ -0,0 +1,33 @@
+unit ProgramOutputUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  ExtCtrls, MemoComponentUnit;
+
+type
+  TProgramOutputForm = class(TForm)
+    OutputMemo: TMemoComponent;
+    ErrorMemo: TMemoComponent;
+		Splitter: TSplitter;
+		Panel1: TPanel;
+    Panel2: TPanel;
+    procedure FormShow(Sender: TObject);
+  private
+	public
+	end;
+
+implementation
+
+{$R *.DFM}
+
+procedure TProgramOutputForm.FormShow(Sender: TObject);
+begin
+	OutputMemo.Selection.RStart := OutputMemo.TextLength + 1;
+	OutputMemo.Selection.ScrollInView (0);
+	ErrorMemo.Selection.RStart := ErrorMemo.TextLength + 1;
+	ErrorMemo.Selection.ScrollInView (0);
+end;
+
+end.

BIN
tigcc/ide/ProjectOptionsUnit.dfm


+ 262 - 0
tigcc/ide/ProjectOptionsUnit.pas

@@ -0,0 +1,262 @@
+unit ProjectOptionsUnit;
+
+interface
+
+uses
+	MasterUnit, ParsingUnit, ProgramOptionsUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ExtCtrls, ComCtrls;
+
+type
+	TProjectOptionsForm = class(TForm)
+		OKButton: TButton;
+		CancelButton: TButton;
+		PageController: TPageControl;
+		GeneralSheet: TTabSheet;
+		CompilationSheet: TTabSheet;
+		LinkingSheet: TTabSheet;
+		PostBuildSheet: TTabSheet;
+		TargetGroupBox: TGroupBox;
+		PackVarEditLabel: TLabel;
+		ExecutableRadioButton: TRadioButton;
+    FlashOSRadioButton: TRadioButton;
+		FargoRadioButton: TRadioButton;
+		ArchiveRadioButton: TRadioButton;
+		PackCheckBox: TCheckBox;
+		PackVarEdit: TEdit;
+		SwitchesGroupBox: TGroupBox;
+		GCCSwitchesEditLabel: TLabel;
+		GCCSwitchesEdit: TEdit;
+		AsSwitchesEditLabel: TLabel;
+		AsSwitchesEdit: TEdit;
+		AsmSwitchesEditLabel: TLabel;
+		AsmSwitchesEdit: TEdit;
+		DebugInfoCheckBox: TCheckBox;
+		OptimizationGroupBox: TGroupBox;
+		OptimizeNOPsCheckBox: TCheckBox;
+		OptimizeReturnsCheckBox: TCheckBox;
+		OptimizeBranchesCheckBox: TCheckBox;
+		OptimizeMovesCheckBox: TCheckBox;
+		OptimizeTestsCheckBox: TCheckBox;
+		OptimizeCalculationsCheckBox: TCheckBox;
+		RemoveUnusedSectionsCheckBox: TCheckBox;
+    ReorderSectionsCheckBox: TCheckBox;
+		CutUnusedRangesCheckBox: TCheckBox;
+		StdLibCheckBox: TCheckBox;
+		OutputBinCheckBox: TCheckBox;
+		BrowseDialog: TOpenDialog;
+		ProcessFileGroupBox: TGroupBox;
+		ProcessFileEditLabel: TLabel;
+		ProcessFileEdit: TEdit;
+		BrowseButton: TButton;
+		ExecutionGroupBox: TGroupBox;
+		CommandLineEditLabel: TLabel;
+		CommandLineEdit: TEdit;
+		DataVarCheckBox: TCheckBox;
+		DataVarEditLabel: TLabel;
+		DataVarEdit: TEdit;
+		DataVarCopyLabel: TLabel;
+		DataVarCopyPanel: TPanel;
+		DataVarCopyNeverRadioButton: TRadioButton;
+		DataVarCopyIfArchivedRadioButton: TRadioButton;
+		DataVarCopyAlwaysRadioButton: TRadioButton;
+		ProgramOptionsButton: TButton;
+    MergeConstantsCheckBox: TCheckBox;
+    InitBSSCheckBox: TCheckBox;
+		procedure FormDestroy(Sender: TObject);
+		procedure FormShow(Sender: TObject);
+		procedure DataVarCheckBoxClick(Sender: TObject);
+		procedure PackCheckBoxClick(Sender: TObject);
+		procedure VarEditChange(Sender: TObject);
+		procedure TargetRadioButtonClick(Sender: TObject);
+		procedure BrowseButtonClick(Sender: TObject);
+		procedure ProgramOptionsButtonClick(Sender: TObject);
+	private
+	public
+		InitialLibOptions: TPredefinedLibOptions;
+		ProgramOptionsForm: TProgramOptionsForm;
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	CalcUnit,
+	MainUnit;
+
+procedure TProjectOptionsForm.FormDestroy(Sender: TObject);
+begin
+	if Assigned (ProgramOptionsForm) then
+		ProgramOptionsForm.Free;
+end;
+
+procedure TProjectOptionsForm.FormShow(Sender: TObject);
+begin
+	TargetRadioButtonClick (Sender);
+end;
+
+procedure TProjectOptionsForm.DataVarCheckBoxClick(Sender: TObject);
+begin
+	DataVarEdit.Enabled := DataVarCheckBox.Checked;
+	DataVarEditLabel.Enabled := DataVarEdit.Enabled;
+	DataVarCopyPanel.Enabled := DataVarEdit.Enabled;
+	DataVarCopyNeverRadioButton.Enabled := DataVarEdit.Enabled;
+	DataVarCopyIfArchivedRadioButton.Enabled := DataVarEdit.Enabled;
+	DataVarCopyAlwaysRadioButton.Enabled := DataVarEdit.Enabled;
+	DataVarCopyLabel.Enabled := DataVarEdit.Enabled;
+	VarEditChange (Sender);
+end;
+
+procedure TProjectOptionsForm.PackCheckBoxClick(Sender: TObject);
+begin
+	PackVarEdit.Enabled := PackCheckBox.Checked;
+	PackVarEditLabel.Enabled := PackVarEdit.Enabled;
+	VarEditChange (Sender);
+end;
+
+procedure TProjectOptionsForm.VarEditChange(Sender: TObject);
+var
+	S: string;
+	I: Integer;
+	OK,
+	HasFolder: Boolean;
+begin
+	if PackCheckBox.Checked then begin
+		S := PackVarEdit.Text;
+		OK := (Length (S) > 0) and (Length (S) <= 8) and (IsCharAlpha (S [1]) or (S [1] in ['A'..'Z', 'a'..'z'])) and (LowerCase (S) <> LowerCase (MainForm.TopNode.Text));
+		if OK then
+			for I := Length (S) downto 1 do
+				if (not (IsCharAlphaNumeric (S [I]) or (S [I] in ['A'..'Z', 'a'..'z', '0'..'9', '_']))) or ((I = 1) and (S [I] = '_')) then begin
+					OK := False;
+					Break;
+				end;
+	end else
+		OK := True;
+	if OK then begin
+		if DataVarCheckBox.Checked then begin
+			S := DataVarEdit.Text;
+			if PackCheckBox.Checked and (LowerCase (DataVarEdit.Text) = LowerCase (PackVarEdit.Text)) then
+				OK := False
+			else begin
+				OK := (Length (S) > 0) and (IsCharAlpha (S [1]) or (S [1] in ['A'..'Z', 'a'..'z'])) and (LowerCase (S) <> LowerCase (MainForm.TopNode.Text));
+				if OK then begin
+					HasFolder := False;
+					for I := Length (S) downto 1 do begin
+						if S [I] = '\' then begin
+							if HasFolder then begin
+								OK := False;
+								Break;
+							end else
+								HasFolder := True;
+						end else if (not (IsCharAlphaNumeric (S [I]) or (S [I] in ['A'..'Z', 'a'..'z', '0'..'9', '_']))) or ((I = 1) and (S [I] = '_')) then begin
+							OK := False;
+							Break;
+						end;
+					end;
+					I := Pos ('\', S);
+					if I > 0 then begin
+						if (I - 1 > MaxNameLength) or (Length (S) - I > MaxNameLength) or (I + 1 > Length (S)) or (not (IsCharAlpha (S [I + 1]) or (S [I + 1] in ['A'..'Z', 'a'..'z']))) then
+							OK := False;
+					end else begin
+						if Length (S) > MaxNameLength then
+							OK := False;
+					end;
+				end;
+			end;
+		end;
+	end;
+	OKButton.Enabled := OK;
+end;
+
+procedure TProjectOptionsForm.TargetRadioButtonClick(Sender: TObject);
+begin
+	LinkingSheet.TabVisible := ExecutableRadioButton.Checked or FlashOSRadioButton.Checked or FargoRadioButton.Checked;
+	PostBuildSheet.TabVisible := LinkingSheet.TabVisible;
+	DataVarCheckBox.Enabled := ExecutableRadioButton.Checked and (ssPack in SpecialSupport);
+	if not DataVarCheckBox.Enabled then
+		DataVarCheckBox.Checked := False;
+	PackCheckBox.Enabled := ExecutableRadioButton.Checked and (ssPack in SpecialSupport);
+	if not PackCheckBox.Enabled then
+		PackCheckBox.Checked := False;
+	OutputBinCheckBox.Enabled := not FlashOSRadioButton.Checked;
+	if not OutputBinCheckBox.Enabled then
+		OutputBinCheckBox.Checked := True;
+	DataVarCheckBoxClick (Sender);
+	PackCheckBoxClick (Sender);
+	ProgramOptionsButton.Visible := ExecutableRadioButton.Checked;
+end;
+
+procedure TProjectOptionsForm.BrowseButtonClick(Sender: TObject);
+var
+	S: string;
+begin
+	with BrowseDialog do begin
+		S := ProcessFileEdit.Text;
+		if (Length (S) > 0) and ((S [1] = '"') or (Pos (' ', S) <= 0)) then begin
+			if S [1] = '"' then begin
+				Delete (S, 1, 1);
+				if Pos ('"', S) > 0 then
+					Delete (S, Pos ('"', S), Length (S));
+			end;
+			FileName := S;
+		end;
+		if Execute then
+			ProcessFileEdit.Text := '"' + FileName + '" "($TI89File)" "($TI92PlusFile)" "($V200File)"';
+	end;
+end;
+
+procedure TProjectOptionsForm.ProgramOptionsButtonClick(Sender: TObject);
+begin
+	if not Assigned (ProgramOptionsForm) then begin
+		ProgramOptionsForm := TProgramOptionsForm.Create(Self);
+		if Assigned (InitialLibOptions) then
+			with ProgramOptionsForm, InitialLibOptions do begin
+				TI89CheckBox.Checked     := cdTI89     in CalcDests;
+				TI92PlusCheckBox.Checked := cdTI92Plus in CalcDests;
+				V200CheckBox.Checked     := cdV200     in CalcDests;
+				OptimizeCalcConstsCheckBox.Checked := OptimizeCalcConsts;
+				case KernelFormat of
+					kfNone:             NoStubRadioButton.Checked := True;
+					kfStandard:         DoorsRadioButton.Checked  := True;
+					kfCompressedTables: PreOsRadioButton.Checked  := True;
+				end;
+				MinAMSCheckBox.Checked := UseMinAMS;
+				MinAMSEdit.Text        := MinAMS;
+				UnofficialOSSupportCheckBox.Checked := UnofficialOSSupport;
+				case RelocFormat of
+					rfAMS:         RelocAMSRadioButton.Checked          := True;
+					rfKernel:      RelocKernelRadioButton.Checked       := True;
+					rfCompressed:  RelocCompressedRadioButton.Checked   := True;
+				end;
+				case ROMCallFormat of
+					rfDirect:      ROMCallDirectRadioButton.Checked     := True;
+					rfKernel:      ROMCallKernelRadioButton.Checked     := True;
+					rfCompressed:  ROMCallCompressedRadioButton.Checked := True;
+					rfFLine:       ROMCallFLineRadioButton.Checked      := True;
+				end;
+				case BSSRefFormat of
+					rfNone:        BSSMergeRadioButton.Checked          := True;
+					rfKernel:      BSSKernelRadioButton.Checked         := True;
+					rfCompressed:  BSSCompressedRadioButton.Checked     := True;
+				end;
+				case DataRefFormat of
+					rfKernel:      DataVarKernelRadioButton.Checked     := True;
+					rfCompressed:  DataVarCompressedRadioButton.Checked := True;
+				end;
+				RelocFLineJumpsCheckBox.Checked      := UseFLineJumps;
+				RelocFLineJumps4ByteCheckBox.Checked := Use4ByteFLineJumps;
+				ROMCallOptimizedCheckBox.Checked := OptimizeROMCalls;
+				InternalFLineEmulatorCheckBox.Checked := UseInternalFLineEmulator;
+				if UseReturnValue then
+					ReturnValueRadioButton.Checked := True
+				else
+					ReturnDoneRadioButton.Checked  := True;
+				EnableErrorReturnCheckBox.Checked := EnableErrorReturn;
+				LCDSaveCheckBox.Checked           := SaveScreen;
+			end;
+	end;
+	ProgramOptionsForm.ShowModal;
+end;
+
+end.

BIN
tigcc/ide/SendProgressUnit.dfm


+ 51 - 0
tigcc/ide/SendProgressUnit.pas

@@ -0,0 +1,51 @@
+unit SendProgressUnit;
+
+interface
+
+uses
+	LinkUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ComCtrls;
+
+type
+	TSendProgressForm = class(TForm)
+		ProgressBar: TProgressBar;
+		FileNameLabel: TLabel;
+		CancelButton: TButton;
+		procedure CancelButtonClick(Sender: TObject);
+		procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+	private
+	public
+		Cancelled: Boolean;
+		CloseNow: Boolean;
+	end;
+
+function ProgressProg(ID: Pointer; Progress: PDWord): Boolean;
+
+implementation
+
+{$R *.DFM}
+
+function ProgressProg(ID: Pointer; Progress: PDWord): Boolean;
+begin
+	with TSendProgressForm (ID) do begin
+		ProgressBar.Position := Progress^;
+		Result := not Cancelled;
+	end;
+	Application.ProcessMessages;
+end;
+
+procedure TSendProgressForm.CancelButtonClick(Sender: TObject);
+begin
+	Cancelled := True;
+end;
+
+procedure TSendProgressForm.FormCloseQuery(Sender: TObject;
+	var CanClose: Boolean);
+begin
+	CanClose := CloseNow;
+	if not CanClose then
+		Cancelled := True;
+end;
+
+end.

+ 2655 - 0
tigcc/ide/SourceFileUnit.pas

@@ -0,0 +1,2655 @@
+unit SourceFileUnit;
+
+interface
+
+uses
+	FolderUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ExtCtrls, ComCtrls,
+	MemoComponentUnit, SourceEditUnit;
+
+type
+	TSourceFile = class;
+
+	TSourceFileType = (ftCFile, ftGNUAsmFile, ftA68kAsmFile, ftQuillFile, ftOther);
+	TBugType = (btError, btWarning, btInfo);
+	TErrorCallback = procedure(const Line: string; BugTp: TBugType; SourceF: string; ErrFunc: string; ErrMessage: string; SourceLn: Integer; Offset: Integer) of object;
+	TSourceFileFunction = record
+		Name: string;
+		PrototypeLine,
+		ImplementationLine: Integer;
+	end;
+	TSourceFileFunctions = array of TSourceFileFunction;
+	PSourceFileFunctions = ^TSourceFileFunctions;
+
+	TSourceFileClass = class of TSourceFile;
+
+	TSourceFiles = class(TCollection)
+	public
+		constructor Create;
+		function FindFile(const FN: string): TSourceFile;
+		function FindFileWithoutExt(const FN: string): TSourceFile;
+		function FindFileNameOnly(const FN: string): TSourceFile;
+		function FindFileOfType(FileType: TSourceFileClass): TSourceFile;
+		function FindFileOfTypeInProject(FileType: TSourceFileClass): TSourceFile;
+	end;
+
+	TSourceFile = class(TCollectionItem)
+	private
+		FFileName: string;
+		FParentForm: TForm;
+		FTreeItem: TTreeNode;
+		FInvalidated: Boolean;
+		FOnError: TErrorCallback;
+		FErrorList: TListView;
+		FModified: Boolean;
+		FFolder: TFolder;
+		function GetSourceName: string;
+		procedure SetSourceName(const Value: string);
+		function GetEditing: Boolean;
+		function GetDynamicName: string;
+		procedure SetEditing(const Value: Boolean);
+		procedure SetCaption(const Value: TCaption);
+		function GetCaption: TCaption;
+		function GetLogicalFileName: string;
+		function GetFolderPath: string;
+	protected
+		Modifying: Boolean;
+		FLastChangeTime: Integer;
+		class function GetCompilable: Boolean; virtual;
+		class function GetPrintable: Boolean; virtual;
+		function GetInProject: Boolean; virtual;
+		procedure SetFileName(const Value: string); virtual;
+		procedure SetModified(const Value: Boolean); virtual;
+		function GetEditor: TWinControl; virtual;
+		procedure ProcessErrors(const ErrText: string); virtual;
+		procedure ProcessErrorLine(Line: string); dynamic;
+	public
+		class function GetClassFilter: string; virtual;
+		class function GetClassItemName: string; virtual;
+		class function GetClassTreeIndex: Integer; virtual;
+		class function GetClassImageIndex: Integer; virtual;
+		destructor Destroy; override;
+		class function GetAppropriateClassFromName(ItemNm: string): TSourceFileClass;
+		class function GetAppropriateClassFromExt(Ext: string): TSourceFileClass;
+		class function GetAppropriateClassFromTreeIndex(Index: Integer): TSourceFileClass;
+		procedure WriteToFile(const FN: string = ''; SetFN: Boolean = False); virtual;
+		procedure LoadFromFile(const FN: string = ''; SetFN: Boolean = False); virtual;
+		procedure Save; virtual;
+		procedure SaveAs; virtual;
+		class function CanSave: Boolean; virtual;
+		procedure Compile; virtual;
+		procedure Print(Copies: Integer; PrintRange: TPrintRange; FromPage, ToPage: Integer); virtual;
+		function CountPages: Integer; virtual;
+		procedure Modify;
+		procedure WarnIfModified;
+		procedure Invalidate;
+		procedure Edit; virtual;
+		procedure TestChange; virtual;
+		procedure UpdateProgramOutput; virtual;
+		property ClassFilter: string read GetClassFilter;
+		property ClassItemName: string read GetClassItemName;
+		property ClassTreeIndex: Integer read GetClassTreeIndex;
+		property ClassImageIndex: Integer read GetClassImageIndex;
+		property Compilable: Boolean read GetCompilable;
+		property Printable: Boolean read GetPrintable;
+		property InProject: Boolean read GetInProject;
+		property Editor: TWinControl read GetEditor;
+		property SourceName: string read GetSourceName write SetSourceName;
+		property DynamicName: string read GetDynamicName;
+	published
+		property FileName: string read FFileName write SetFileName;
+		property Editing: Boolean read GetEditing write SetEditing;
+		property Modified: Boolean read FModified write SetModified;
+		property Invalidated: Boolean read FInvalidated write FInvalidated;
+		property TreeItem: TTreeNode read FTreeItem write FTreeItem;
+		property ParentForm: TForm read FParentForm write FParentForm;
+		property ErrorList: TListView read FErrorList write FErrorList;
+		property Caption: TCaption read GetCaption write SetCaption;
+		property OnError: TErrorCallback read FOnError write FOnError;
+		property Folder: TFolder read FFolder write FFolder;
+		property FolderPath: string read GetFolderPath;
+		property LogicalFileName: string read GetLogicalFileName;
+	end;
+
+	TTextSourceFile = class(TSourceFile)
+	private
+		FModifyLevel: Integer;
+	protected
+		LineStartList: TIntegerList;
+		FTempContent: string;
+		class function GetPrintable: Boolean; override;
+		function GetEditor: TWinControl; override;
+		function GetTextEditor: TMemoComponent; virtual; abstract;
+		function GetInternalTextEditor: TMemoComponent; virtual; abstract;
+		function GetContent: string; virtual;
+		procedure SetContent(const Value: string); virtual;
+		procedure SetModified(const Value: Boolean); override;
+		procedure Change(Sender: TObject); virtual;
+		procedure ReplaceText(Sender: TObject; Pos, Change: Integer); virtual;
+		procedure SetParentForm(const Value: TForm); virtual;
+		property InternalTextEditor: TMemoComponent read GetInternalTextEditor;
+	public
+		destructor Destroy; override;
+		procedure WriteToFile(const FN: string = ''; SetFN: Boolean = False); override;
+		procedure LoadFromFile(const FN: string = ''; SetFN: Boolean = False); override;
+		procedure Print(Copies: Integer; PrintRange: TPrintRange; FromPage, ToPage: Integer); override;
+		function CountPages: Integer; override;
+		procedure TestChange; override;
+		procedure AskForReload; virtual;
+		procedure UpdateEditor; virtual;
+		function GetLineContents(StartLine, EndLine: Integer): string;
+		function GetCompiledLineStart(Line: Integer): Integer; virtual;
+		property TextEditor: TMemoComponent read GetTextEditor;
+		property Content: string read GetContent write SetContent;
+	end;
+
+	TBinarySourceFile = class(TSourceFile)
+	public
+		class function CanSave: Boolean; override;
+		procedure WriteToFile(const FN: string = ''; SetFN: Boolean = False); override;
+	end;
+
+	TNormalTextSourceFile = class(TTextSourceFile)
+	private
+		FEditor: TMemoComponent;
+	protected
+		function GetTextEditor: TMemoComponent; override;
+		function GetInternalTextEditor: TMemoComponent; override;
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+		destructor Destroy; override;
+	end;
+
+	TSourceTextSourceFile = class(TTextSourceFile)
+	private
+		FEditor: TSourceEdit;
+		function GetSourceEditor: TSourceEdit;
+	protected
+		function GetTextEditor: TMemoComponent; override;
+		function GetInternalTextEditor: TMemoComponent; override;
+		function GetContentType: TSourceFileType; virtual;
+		property InternalSourceEditor: TSourceEdit read FEditor;
+	public
+		destructor Destroy; override;
+		procedure UpdateSyntax; virtual; abstract;
+		procedure UpdateEditor; override;
+		procedure SplitAndWriteToFile(const FN: string); virtual;
+		function GetFunctions: TSourceFileFunctions; virtual;
+		property SourceEditor: TSourceEdit read GetSourceEditor;
+		property ContentType: TSourceFileType read GetContentType;
+	end;
+
+	THeaderSourceFile = class(TSourceTextSourceFile)
+	protected
+		procedure SetContent(const Value: string); override;
+		procedure SetModified(const Value: Boolean); override;
+		function GetContentType: TSourceFileType; override;
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+		procedure UpdateSyntax; override;
+		procedure UpdateEditor; override;
+		procedure UpdateContentType(CT: TSourceFileType); virtual;
+	end;
+
+	TCSourceFile = class(TSourceTextSourceFile)
+	private
+		FSFileChangedLines: TIntegerList;
+		FSFileLineChanges: TIntegerList;
+	protected
+		CurErrFunction: string;
+		InAssemblingState: Boolean;
+		SpecialSwitches: string;
+		class function GetCompilable: Boolean; override;
+		procedure SetModified(const Value: Boolean); override;
+		function GetContentType: TSourceFileType; override;
+		procedure SFileLineChange(StartLine, Change: Integer);
+		procedure SFileMapLine(var Line: Integer);
+		procedure SFileClear;
+		procedure ProcessErrorLine(Line: string); override;
+		procedure ProcessSFile(const SourceFile, DestFile: string);
+	public
+		destructor Destroy; override;
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+		procedure Save; override;
+		procedure Compile; override;
+		procedure UpdateSyntax; override;
+		procedure UpdateEditor; override;
+	end;
+
+	TGNUAsmSourceFile = class(TSourceTextSourceFile)
+	protected
+		class function GetCompilable: Boolean; override;
+		procedure SetModified(const Value: Boolean); override;
+		function GetContentType: TSourceFileType; override;
+		procedure ProcessErrorLine(Line: string); override;
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+		procedure Save; override;
+		procedure Compile; override;
+		procedure UpdateSyntax; override;
+		procedure UpdateEditor; override;
+	end;
+
+	TAsmSourceFile = class(TSourceTextSourceFile)
+	protected
+		class function GetCompilable: Boolean; override;
+		procedure SetModified(const Value: Boolean); override;
+		function GetContentType: TSourceFileType; override;
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+		procedure Save; override;
+		procedure Compile; override;
+		procedure UpdateSyntax; override;
+		procedure UpdateEditor; override;
+	end;
+
+	TQuillSourceFile = class(TCSourceFile)
+	protected
+		function GetContentType: TSourceFileType; override;
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+		procedure Compile; override;
+		procedure UpdateSyntax; override;
+	end;
+
+	TObjectSourceFile = class(TBinarySourceFile)
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+	end;
+
+	TArchiveSourceFile = class(TBinarySourceFile)
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+	end;
+
+	TOtherSourceFile = class(TBinarySourceFile)
+	public
+		class function GetClassFilter: string; override;
+		class function GetClassItemName: string; override;
+		class function GetClassTreeIndex: Integer; override;
+		class function GetClassImageIndex: Integer; override;
+	end;
+
+	TFoundError = class(TObject)
+	public
+		WholeLine: string;
+		BugType: TBugType;
+		ErrFunction: string;
+		ErrorMessage: string;
+		SourceFile: TSourceFile;
+		Range: TMCRange;
+		destructor Destroy; override;
+		procedure GoToPosition;
+	end;
+
+var
+	AppNode: TTreeNode;
+	NoEditor: TWinControl;
+
+implementation
+
+uses
+	Printers,
+	MasterUnit, ParsingUnit, ProcessUnit,
+	UtilsDos, UtilsWin,
+	HandleWaitThreadUnit, FileReadToBufferThreadUnit;
+
+const
+	CSingleSymbols: set of Char = [',', ';', '(', ')', '[', ']', '{', '}'];
+	AdditionalLinesPerPage = 4;
+
+{ TFoundError }
+
+destructor TFoundError.Destroy;
+begin
+	if Assigned (Range) then begin
+		Range.Free;
+		Range := nil;
+	end;
+	inherited;
+end;
+
+procedure TFoundError.GoToPosition;
+begin
+	if Assigned (SourceFile) then begin
+		with SourceFile do begin
+			if Assigned (Editor) then begin
+				Edit;
+				if SourceFile is TSourceTextSourceFile then
+					with SourceFile as TSourceTextSourceFile do
+						with SourceEditor do begin
+							if Assigned (Range) then begin
+								with Selection do begin
+									Assign (Range);
+									ScrollInView (5);
+								end;
+								SetFocus;
+							end;
+						end;
+			end;
+		end;
+	end else
+		AppNode.Selected := True;
+end;
+
+{ TSourceFiles }
+
+constructor TSourceFiles.Create;
+begin
+	inherited Create (TSourceFile);
+end;
+
+function TSourceFiles.FindFile(const FN: string): TSourceFile;
+var
+	I: Integer;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do
+		with Items [I] as TSourceFile do
+			if UpperCase (FN) = UpperCase (FileName) then begin
+				Result := Items [I] as TSourceFile;
+				Break;
+			end;
+end;
+
+function TSourceFiles.FindFileNameOnly(const FN: string): TSourceFile;
+var
+	I: Integer;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do
+		with Items [I] as TSourceFile do
+			if UpperCase (FN) = UpperCase (ExtractFileName (FileName)) then begin
+				Result := Items [I] as TSourceFile;
+				Break;
+			end;
+end;
+
+function TSourceFiles.FindFileOfType(FileType: TSourceFileClass):
+	TSourceFile;
+var
+	I: Integer;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do
+		if Items [I] is FileType then begin
+			Result := Items [I] as TSourceFile;
+			Break;
+		end;
+end;
+
+function TSourceFiles.FindFileOfTypeInProject(FileType: TSourceFileClass):
+	TSourceFile;
+var
+	I: Integer;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do
+		if (Items [I] is FileType) and (Items [I] as TSourceFile).InProject then begin
+			Result := Items [I] as TSourceFile;
+			Break;
+		end;
+end;
+
+function TSourceFiles.FindFileWithoutExt(const FN: string): TSourceFile;
+var
+	I: Integer;
+begin
+	Result := nil;
+	for I := 0 to Count - 1 do
+		with Items [I] as TSourceFile do
+			if UpperCase (FN) = UpperCase (WithoutExt (FileName)) then begin
+				Result := Items [I] as TSourceFile;
+				Break;
+			end;
+end;
+
+{ TSourceFile }
+
+class function TSourceFile.CanSave: Boolean;
+begin
+	Result := True;
+end;
+
+procedure TSourceFile.Compile;
+begin
+end;
+
+function TSourceFile.CountPages: Integer;
+begin
+	Result := 0;
+end;
+
+destructor TSourceFile.Destroy;
+var
+	I: Integer;
+	F: TForm;
+	N: TTreeNode;
+begin
+	if Assigned (ErrorList) then
+		with ErrorList.Items do begin
+			BeginUpdate;
+			for I := Count - 1 downto 0 do
+				if Assigned (Item[I].Data) then
+					with TFoundError (Item[I].Data) do
+						if SourceFile = Self then begin
+							Range := nil;
+							Item[I].Delete;
+						end;
+			EndUpdate;
+		end;
+	if Assigned (OnError) then
+		OnError ('', btWarning, FileName, '', '', 0, 0);
+	if Assigned (ParentForm) then begin
+		F := ParentForm;
+		ParentForm := nil;
+		F.Free;
+	end;
+	if Assigned (TreeItem) then begin
+		N := TreeItem;
+		TreeItem := nil;
+		N.Data := nil;
+		N.Free;
+	end;
+	inherited;
+end;
+
+procedure TSourceFile.Edit;
+begin
+	if Assigned (TreeItem) then
+		TreeItem.Selected := True
+	else if Assigned (ParentForm) then begin
+		ParentForm.Show;
+		ParentForm.SetFocus;
+	end;
+end;
+
+class function TSourceFile.GetAppropriateClassFromExt(Ext: string): TSourceFileClass;
+begin
+	Ext := LowerCase (Ext);
+	if (Length (Ext) > 0) and (Ext [1] <> '.') then
+		Ext := '.' + Ext;
+	if Ext = '.h' then
+		Result := THeaderSourceFile
+	else if Ext = '.c' then
+		Result := TCSourceFile
+	else if Ext = '.s' then
+		Result := TGNUAsmSourceFile
+	else if Ext = '.asm' then begin
+		if ssA68k in SpecialSupport then
+			Result := TAsmSourceFile
+		else
+			Result := TGNUAsmSourceFile;
+	end else if (Ext = '.qll') and (ssQuill in SpecialSupport) then
+		Result := TQuillSourceFile
+	else if Ext = '.o' then
+		Result := TObjectSourceFile
+	else if Ext = '.a' then
+		Result := TArchiveSourceFile
+	else if Ext = '.txt' then
+		Result := TNormalTextSourceFile
+	else
+		Result := TOtherSourceFile;
+end;
+
+class function TSourceFile.GetAppropriateClassFromName(ItemNm: string): TSourceFileClass;
+procedure CheckClass(AClass: TSourceFileClass);
+begin
+	if (not Assigned (Result)) and (ItemNm = UpperCase (AClass.GetClassItemName)) then
+		Result := AClass;
+end;
+begin
+	ItemNm := UpperCase (ItemNm);
+	Result := nil;
+	CheckClass (THeaderSourceFile);
+	CheckClass (TCSourceFile);
+	CheckClass (TGNUAsmSourceFile);
+	CheckClass (TAsmSourceFile);
+	CheckClass (TQuillSourceFile);
+	CheckClass (TObjectSourceFile);
+	CheckClass (TArchiveSourceFile);
+	CheckClass (TNormalTextSourceFile);
+	CheckClass (TOtherSourceFile);
+	if (Result = TAsmSourceFile) and (not (ssA68k in SpecialSupport)) then
+		Result := TGNUAsmSourceFile
+	else if (Result = TQuillSourceFile) and (not (ssQuill in SpecialSupport)) then
+		Result := TQuillSourceFile;
+end;
+
+class function TSourceFile.GetAppropriateClassFromTreeIndex(Index: Integer): TSourceFileClass;
+procedure CheckClass(AClass: TSourceFileClass);
+begin
+	if (not Assigned (Result)) and (Index = AClass.GetClassTreeIndex) then
+		Result := AClass;
+end;
+begin
+	Result := nil;
+	CheckClass (THeaderSourceFile);
+	CheckClass (TCSourceFile);
+	CheckClass (TGNUAsmSourceFile);
+	if ssA68k in SpecialSupport then
+		CheckClass (TAsmSourceFile);
+	if ssQuill in SpecialSupport then
+		CheckClass (TQuillSourceFile);
+	CheckClass (TObjectSourceFile);
+	CheckClass (TArchiveSourceFile);
+	CheckClass (TNormalTextSourceFile);
+	CheckClass (TOtherSourceFile);
+end;
+
+function TSourceFile.GetCaption: TCaption;
+begin
+	if Assigned (TreeItem) then
+		Result := TreeItem.Text
+	else if Assigned (ParentForm) then
+		Result := ParentForm.Caption
+	else
+		Result := '';
+end;
+
+class function TSourceFile.GetClassFilter: string;
+begin
+	Result := 'Abstract Files (*.*)|*.*';
+end;
+
+class function TSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := -1;
+end;
+
+class function TSourceFile.GetClassItemName: string;
+begin
+	Result := 'Abstract File';
+end;
+
+class function TSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := -1;
+end;
+
+class function TSourceFile.GetCompilable: Boolean;
+begin
+	Result := False;
+end;
+
+function TSourceFile.GetDynamicName: string;
+var
+	S: string;
+begin
+	S := ExtractFilePath (FileName);
+	if StartsWith (ExtractFilePath (ProjectFileName), S) then
+		Result := Copy (FileName, Length (ExtractFilePath (ProjectFileName)) + 1, Length (FileName))
+	else
+		Result := FileName;
+end;
+
+function TSourceFile.GetEditing: Boolean;
+begin
+	if Assigned (TreeItem) then
+		Result := TreeItem.Selected
+	else if Assigned (ParentForm) then
+		Result := ParentForm.Visible
+	else
+		Result := False;
+end;
+
+function TSourceFile.GetEditor: TWinControl;
+begin
+	if Assigned (TreeItem) then
+		Result := NoEditor
+	else
+		Result := nil;
+end;
+
+function TSourceFile.GetFolderPath: string;
+begin
+	if Assigned (Folder) then
+		Result := Folder.Path
+	else
+		Result := '';
+end;
+
+function TSourceFile.GetInProject: Boolean;
+begin
+	Result := Assigned (TreeItem);
+end;
+
+function TSourceFile.GetLogicalFileName: string;
+var
+	Path: string;
+begin
+	Result := ExtractFileName (FileName);
+	Path := FolderPath;
+	if Length (Path) > 0 then
+		Result := WithBackslash (Path) + Result;
+end;
+
+class function TSourceFile.GetPrintable: Boolean;
+begin
+	Result := False;
+end;
+
+function TSourceFile.GetSourceName: string;
+begin
+	Result := WithoutExt (ExtractFileName (FileName));
+end;
+
+procedure TSourceFile.Invalidate;
+begin
+	Invalidated := True;
+end;
+
+procedure TSourceFile.LoadFromFile(const FN: string; SetFN: Boolean);
+begin
+	if SetFN and (Length (FN) > 0) then
+		FFileName := FN; 
+	Modified := False;
+end;
+
+procedure TSourceFile.Modify;
+begin
+	Modified := True;
+	Invalidate;
+end;
+
+procedure TSourceFile.Print(Copies: Integer; PrintRange: TPrintRange; FromPage, ToPage: Integer);
+begin
+end;
+
+procedure TSourceFile.ProcessErrorLine(Line: string);
+begin
+end;
+
+procedure TSourceFile.ProcessErrors(const ErrText: string);
+var
+	I: Integer;
+	LL: TStringList;
+begin
+	UpdateProgramOutput;
+	if not OperationCancelled then begin
+		LL := TStringList.Create;
+		with LL do try
+			Text := ErrText;
+			if Count > 0 then begin
+				if Assigned (ErrorList) then
+					ErrorList.Items.BeginUpdate;
+				try
+					for I := 0 to Count - 1 do
+						ProcessErrorLine (Strings [I]);
+				finally
+					if Assigned (ErrorList) then
+						ErrorList.Items.EndUpdate;
+				end;
+			end;
+		except end;
+		LL.Free;
+		CompUpdate;
+	end;
+end;
+
+procedure TSourceFile.Save;
+begin
+	if (ProjectFileName = '') and (ExtractFilePath (FileName) = 'C:\') then
+		SaveAs
+	else begin
+		FLastChangeTime := 0;
+		WriteToFile;
+		Modified := False;
+	end;
+end;
+
+procedure TSourceFile.SaveAs;
+var
+	S: string;
+begin
+	with TSaveDialog.Create (Application.MainForm) do try
+		Title := 'Save Source File';
+		S := ClassFilter + '|All Files (*.*)|*.*';
+		if S [1] = '|' then
+			Delete (S, 1, 1);
+		Filter := S;
+		FilterIndex := 0;
+		DefaultExt := Copy (ExtractFileExt (Self.FileName), 2, Length (Self.FileName));
+		FileName := Self.FileName;
+		Options := [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist];
+		if Execute then
+			WriteToFile (FileName, True)
+		else
+			Abort;
+	finally
+		Free;
+	end;
+end;
+
+procedure TSourceFile.SetCaption(const Value: TCaption);
+begin
+	if Value <> Caption then begin
+		if Assigned (TreeItem) then
+			TreeItem.Text := Value;
+		if Assigned (ParentForm) then
+			ParentForm.Caption := Value;
+	end;
+end;
+
+procedure TSourceFile.SetEditing(const Value: Boolean);
+begin
+	if Value then
+		Edit
+	else
+		AppNode.Selected := True;
+end;
+
+procedure TSourceFile.SetFileName(const Value: string);
+begin
+	if FFileName <> Value then begin
+		if FileExists (Value) then
+			raise EWriteError.Create ('The file "' + Value + '" already exists.')
+		else
+			if FileExists (FFileName) then begin
+				RenameFile (FFileName, Value);
+				if (LowerCase (ExtractFileExt (FFileName)) <> '.o') and FileExists (ChangeFileExt (FFileName, '.o')) then
+					RenameFile (ChangeFileExt (FFileName, '.o'), ChangeFileExt (Value, '.o'));
+				if (LowerCase (ExtractFileExt (FFileName)) <> '.s') and FileExists (ChangeFileExt (FFileName, '.s')) then
+					RenameFile (ChangeFileExt (FFileName, '.s'), ChangeFileExt (Value, '.s'));
+			end;
+		FFileName := Value;
+	end;
+end;
+
+procedure TSourceFile.SetModified(const Value: Boolean);
+begin
+	FModified := Value;
+	Invalidated := False;
+end;
+
+procedure TSourceFile.SetSourceName(const Value: string);
+begin
+	FileName := WithBackslash (ExtractFilePath (FileName)) + Value + ExtractFileExt (FileName);
+end;
+
+procedure TSourceFile.TestChange;
+begin
+end;
+
+procedure TSourceFile.UpdateProgramOutput;
+begin
+	if Assigned (CompUpdateProgramOutput) then
+		CompUpdateProgramOutput;
+end;
+
+procedure TSourceFile.WarnIfModified;
+begin
+	if Modified then
+		case ShowDefaultMessageBox
+			('The file ''' + SourceName + ''' has been modified.  Do you want to save the changes?',
+			'File Modified', mtQuestion, True) of
+			idYes: Save;
+			idNo: Modified := False;
+			idCancel: Abort;
+		end;
+end;
+
+procedure TSourceFile.WriteToFile(const FN: string; SetFN: Boolean);
+begin
+	if SetFN and (Length (FN) > 0) then
+		FFileName := FN;
+	if SetFN or (Length (FN) <= 0) then begin
+		FLastChangeTime := 0;
+		Caption := SourceName;
+		Modified := False;
+	end;
+end;
+
+{ TTextSourceFile }
+
+procedure TTextSourceFile.AskForReload;
+begin
+	if ShowDefaultMessageBox ('The File "' + SourceName + '" has been changed by another program. Do you want to reload it?', 'File Changed', mtQuestion) = idYes then begin
+		try
+			LoadFromFile;
+		except end;
+		Invalidate;
+	end;
+end;
+
+procedure TTextSourceFile.Change(Sender: TObject);
+begin
+	if (FModifyLevel <= 0) and (not Modifying) then
+		Modify;
+end;
+
+function TTextSourceFile.CountPages: Integer;
+var
+	FontHeight,
+	LinesPerPage: Integer;
+begin
+	if Assigned (TextEditor) then begin
+		Printer.Canvas.Font.Assign (TextEditor.Font);
+		FontHeight := Printer.Canvas.TextHeight ('Gg');
+		LinesPerPage := Printer.PageHeight div FontHeight - AdditionalLinesPerPage;
+		Result := TextEditor.LineCount div LinesPerPage + 1;
+	end else
+		Result := 0;
+end;
+
+destructor TTextSourceFile.Destroy;
+begin
+	if Assigned (LineStartList) then begin
+		LineStartList.Free;
+		LineStartList := nil;
+	end;
+	inherited;
+end;
+
+function TTextSourceFile.GetCompiledLineStart(Line: Integer): Integer;
+begin
+	if (Line > 0) and Assigned (TextEditor) then begin
+		if Assigned (LineStartList) then
+			with LineStartList do begin
+				if Line >= Count then
+					Result := TextEditor.TextLength + 1
+				else
+					Result := Items [Line];
+			end
+		else
+			Result := TextEditor.CellToCharIdx (TextCell (Line, 1));
+	end else
+		Result := 0;
+end;
+
+function TTextSourceFile.GetContent: string;
+begin
+	if Assigned (InternalTextEditor) then
+		Result := InternalTextEditor.Text
+	else
+		Result := FTempContent;
+end;
+
+function TTextSourceFile.GetEditor: TWinControl;
+begin
+	Result := TextEditor;
+end;
+
+function TTextSourceFile.GetLineContents(StartLine, EndLine: Integer): string;
+var
+	Start: Integer;
+begin
+	if Assigned (TextEditor) then begin
+		Start := GetCompiledLineStart (StartLine);
+		Result := Copy (TextEditor.Text, Start, GetCompiledLineStart (EndLine + 1) - Start);
+	end else
+		Result := '';
+end;
+
+class function TTextSourceFile.GetPrintable: Boolean;
+begin
+	Result := True;
+end;
+
+procedure TTextSourceFile.LoadFromFile(const FN: string; SetFN: Boolean);
+begin
+	if Assigned (InternalTextEditor) then
+		InternalTextEditor.AllowUndo := False;
+	Inc (FModifyLevel);
+	try
+		with TMemoryStream.Create do try
+			if Length (FN) > 0 then
+				LoadFromFile (FN)
+			else
+				LoadFromFile (FileName);
+			Size := Size + 1;
+			PChar (Memory) [Size - 1] := #0;
+			Content := AnsiString (PChar (Memory));
+		finally
+			Free;
+		end;
+	finally
+		Dec (FModifyLevel);
+		if Assigned (InternalTextEditor) then
+			InternalTextEditor.AllowUndo := True;
+		inherited;
+		if Compilable then begin
+			if FileExists (ChangeFileExt (FileName, '.o')) then
+				Invalidated := FileAge (ChangeFileExt (FileName, '.o')) < FileAge (FileName)
+			else
+				Invalidated := True;
+		end else
+			Invalidated := False;
+	end;
+end;
+
+procedure TTextSourceFile.Print(Copies: Integer; PrintRange: TPrintRange; FromPage, ToPage: Integer);
+var
+	CurPage,
+	CurPageLine,
+	CurY,
+	FontHeight,
+	LinesPerPage: Integer;
+	procedure StartPage;
+	var
+		PrevStyle: TFontStyles;
+		PageStr: string;
+	begin
+		Inc (CurPage);
+		if CurPage in [FromPage..ToPage] then
+			with Printer.Canvas do begin
+				PrevStyle := Font.Style;
+				Font.Style := PrevStyle + [fsBold];
+				TextOut (0, FontHeight, '  ' + ExtractFileName (FileName));
+				PageStr := 'Page ' + IntToStr (CurPage) + '  ';
+				TextOut (Printer.PageWidth - TextWidth (PageStr), FontHeight, PageStr);
+				Font.Style := PrevStyle;
+			end;
+		CurY := FontHeight * 3;
+		CurPageLine := 1;
+	end;
+var
+	Remaining,
+	S: string;
+	P,
+	Ps,
+	NextPs: Integer;
+begin
+	if Assigned (TextEditor) then begin
+		Printer.Title := 'TIGCC IDE - ' + ExtractFileName (FileName);
+		Printer.Copies := Copies;
+		Printer.BeginDoc;
+		try
+			Printer.Canvas.Font.Assign (TextEditor.Font);
+			FontHeight := Printer.Canvas.TextHeight ('Gg');
+			LinesPerPage := Printer.PageHeight div FontHeight - AdditionalLinesPerPage;
+			if PrintRange <> prPageNums then begin
+				FromPage := 1;
+				ToPage := High (ToPage);
+			end;
+			if PrintRange = prSelection then
+				Remaining := TextEditor.Selection.Text
+			else
+				Remaining := Content;
+			CurPage := 0;
+			StartPage;
+			while (Length (Remaining) > 0) and (CurPage <= ToPage) do begin
+				P := Pos (#13#10, Remaining);
+				if P <= 0 then
+					P := Length (Remaining) + 1;
+				S := Copy (Remaining, 1, P - 1);
+				Delete (Remaining, 1, P + 1);
+				Ps := 1;
+				while Ps <= Length (S) do begin
+					if S [Ps] = #9 then begin
+						NextPs := ((Ps - 1) div TextEditor.TabSize + 1) * TextEditor.TabSize + 1;
+						System.Delete (S, Ps, 1);
+						System.Insert (StringOfChar (' ', NextPs - Ps), S, Ps);
+						Ps := NextPs;
+					end else
+						Inc (Ps);
+				end;
+				if CurPage in [FromPage..ToPage] then
+					Printer.Canvas.TextOut (0, CurY, '  ' + S);
+				Inc (CurPageLine);
+				if CurPageLine > LinesPerPage then begin
+					if CurPage in [FromPage..(ToPage-1)] then
+						Printer.NewPage;
+					StartPage;
+				end else
+					Inc (CurY, FontHeight);
+			end;
+		finally
+			Printer.EndDoc;
+		end;
+	end;
+end;
+
+procedure TTextSourceFile.ReplaceText(Sender: TObject; Pos,
+	Change: Integer);
+var
+	I,
+	FirstChangeI,
+	FirstChangePos: Integer;
+begin
+	if Assigned (LineStartList) then
+		with LineStartList do begin
+			FirstChangeI := -1;
+			FirstChangePos := -1;
+			for I := 0 to Count - 1 do
+				if Items [I] > Pos then begin
+					FirstChangeI := I;
+					FirstChangePos := Items [I];
+					Break;
+				end;
+			if FirstChangeI >= 0 then begin
+				for I := FirstChangeI to Count - 1 do
+					Items [I] := Items [I] + Change;
+				for I := FirstChangeI to Count - 1 do begin
+					if Items [I] >= FirstChangePos then
+						Break;
+					Items [I] := FirstChangePos;
+				end;
+			end;
+		end;
+end;
+
+procedure TTextSourceFile.SetContent(const Value: string);
+begin
+	if Assigned (InternalTextEditor) then begin
+		with InternalTextEditor do
+			Text := Value;
+	end else
+		FTempContent := Value;
+end;
+
+procedure TTextSourceFile.SetModified(const Value: Boolean);
+begin
+	if not Modifying then begin
+		Modifying := True;
+		FModified := Value;
+		Invalidated := False;
+		Modifying := False;
+	end;
+end;
+
+procedure TTextSourceFile.SetParentForm(const Value: TForm);
+begin
+	inherited;
+	if Assigned (TextEditor) then
+		with TextEditor do begin
+			Parent := Value;
+			if Value <> nil then
+				Show;
+		end;
+end;
+
+procedure TTextSourceFile.TestChange;
+var
+	NewTime: Integer;
+	TimeChanged: Boolean;
+begin
+	if (Length (FileName) > 0) and FileExists (FileName) then begin
+		NewTime := FileAge (FileName);
+		TimeChanged := (FLastChangeTime <> 0) and (FLastChangeTime <> NewTime);
+		FLastChangeTime := NewTime;
+		if TimeChanged then
+			AskForReload;
+	end;
+end;
+
+procedure TTextSourceFile.UpdateEditor;
+begin
+	if Assigned (TextEditor) then
+		with TextEditor do begin
+			Color := EditorColor;
+			Font.Assign (EditorFont);
+			DragDropEditing := EditorDragDrop;
+			RemoveTrailingSpaces := EditorRemoveTrSp;
+		end;
+end;
+
+procedure TTextSourceFile.WriteToFile(const FN: string; SetFN: Boolean);
+var
+	WriteFile: string;
+begin
+	if Assigned (TextEditor) then try
+		if Length (FN) > 0 then
+			WriteFile := FN
+		else
+			WriteFile := FileName;
+		CreatePathFor (WriteFile);
+		with TFileStream.Create (WriteFile, fmCreate or fmShareExclusive) do try
+			Write (PChar(TextEditor.Text)^, TextEditor.TextLength);
+		finally
+			Free;
+		end;
+		inherited;
+	except
+		ShowDefaultMessageBox ('Error saving source file.', 'Error', mtProgramError);
+	end;
+end;
+
+{ TBinarySourceFile }
+
+class function TBinarySourceFile.CanSave: Boolean;
+begin
+	Result := False;
+end;
+
+procedure TBinarySourceFile.WriteToFile(const FN: string; SetFN: Boolean);
+begin
+	if Length (FN) > 0 then
+		CopyFile (PChar (FileName), PChar (FN), False);
+	inherited;
+end;
+
+{ THeaderSourceFile }
+
+class function THeaderSourceFile.GetClassFilter: string;
+begin
+	Result := 'Header Files (*.h)|*.h';
+end;
+
+class function THeaderSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 3;
+end;
+
+class function THeaderSourceFile.GetClassItemName: string;
+begin
+	Result := 'Header File';
+end;
+
+class function THeaderSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 0;
+end;
+
+function THeaderSourceFile.GetContentType: TSourceFileType;
+begin
+	Result := ftOther;
+	if Content <> '' then begin
+		if Content [1] = '/' then
+			Result := ftCFile
+		else if Content [1] = '|' then
+			Result := ftGNUAsmFile
+		else if Content [1] = ';' then
+			Result := ftA68kAsmFile;
+	end;
+	if Result = ftOther then
+		if Assigned (Collection) and (Collection is TSourceFiles) then
+			with Collection as TSourceFiles do
+				if Assigned (FindFileOfType (TCSourceFile)) then
+					Result := ftCFile
+				else if Assigned (FindFileOfType (TGNUAsmSourceFile)) then
+					Result := ftGNUAsmFile
+				else if Assigned (FindFileOfType (TAsmSourceFile)) then
+					Result := ftA68kAsmFile
+				else if Assigned (FindFileOfType (TQuillSourceFile)) then
+					Result := ftQuillFile;
+end;
+
+procedure THeaderSourceFile.SetContent(const Value: string);
+begin
+	if Length (Value) > 0 then begin
+		if Value [1] = '/' then
+			UpdateContentType (ftCFile)
+		else if Value [1] = '|' then
+			UpdateContentType (ftGNUAsmFile)
+		else if Value [1] = ';' then
+			UpdateContentType (ftA68kAsmFile);
+	end;
+	inherited;
+end;
+
+procedure THeaderSourceFile.SetModified(const Value: Boolean);
+begin
+	if not Modifying then begin
+		Modifying := True;
+		FModified := Value;
+		if Value then
+			Invalidate;
+		Modifying := False;
+	end;
+end;
+
+procedure THeaderSourceFile.UpdateContentType(CT: TSourceFileType);
+begin
+	if Assigned (InternalSourceEditor) then
+		with InternalSourceEditor do begin
+			if CT = ftGNUAsmFile then begin
+				SyntaxColoring.Assign (SyntaxAsmGNU);
+				TabSize := TabSizeAsm;
+			end else if CT = ftA68kAsmFile then begin
+				SyntaxColoring.Assign (SyntaxAsm);
+				TabSize := TabSizeAsm;
+			end else if CT = ftQuillFile then begin
+				SyntaxColoring.Assign (SyntaxQuill);
+				TabSize := TabSizeC;
+			end else begin
+				SyntaxColoring.Assign (SyntaxC);
+				TabSize := TabSizeC;
+			end;
+			AutoIndentIncrease := AutoBlocks and (CT = ftCFile);
+		end;
+end;
+
+procedure THeaderSourceFile.UpdateEditor;
+begin
+	inherited;
+	if Assigned (SourceEditor) then begin
+		if ContentType = ftCFile then begin
+			SourceEditor.TabSize := TabSizeC;
+			SourceEditor.AutoIndentIncrease := AutoBlocks;
+		end else if ContentType = ftCFile then
+			SourceEditor.TabSize := TabSizeC
+		else
+			SourceEditor.TabSize := TabSizeAsm;
+	end;
+end;
+
+procedure THeaderSourceFile.UpdateSyntax;
+begin
+	UpdateContentType (ContentType);
+end;
+
+{ TSourceTextSourceFile }
+
+destructor TSourceTextSourceFile.Destroy;
+var
+	PrevEditor: TSourceEdit;
+begin
+	if Assigned (FEditor) then begin
+		PrevEditor := FEditor;
+		FEditor := nil;
+		PrevEditor.Free;
+	end;
+	inherited;
+end;
+
+function TSourceTextSourceFile.GetContentType: TSourceFileType;
+begin
+	Result := ftOther;
+end;
+
+function TSourceTextSourceFile.GetFunctions: TSourceFileFunctions;
+var
+	Editor: TSourceEdit;
+	TextLength,
+	I,
+	J,
+	CurPos,
+	WordIndex: Integer;
+	Text,
+	LastWord,
+	FirstWord: string;
+	InFunc,
+	InAsm,
+	InCompSM,
+	InSpace,
+	LineDone: Boolean;
+begin
+	SetLength (Result, 0);
+	Editor := SourceEditor;
+	if not Assigned (Editor) then
+		Exit;
+	Text := Content;
+	TextLength := Length (Text);
+	InFunc := False;
+	InAsm := False;
+	InCompSM := False;
+	case ContentType of
+		ftCFile:
+			for I := 1 to Editor.LineCount do begin
+				CurPos := Editor.CellToCharIdx (TextCell (I, 1));
+				if (CurPos <= TextLength) and (Text [CurPos] <> #13) and (Text [CurPos] <> '*') then begin
+					if InCompSM and (CurPos - 3 >= 1) and (Text [CurPos - 3] <> '\') then
+						InCompSM := False;
+					if not InCompSM then begin
+						if Text [CurPos] = '{' then
+							InFunc := True;
+						if InFunc then begin
+							if Text [CurPos] = '}' then
+								InFunc := False;
+						end else begin
+							if (Copy (Text, CurPos, 5) = 'asm("') or (Copy (Text, CurPos, 6) = 'asm ("') then
+								InAsm := True;
+							if InAsm then begin
+								if Pos ('")', Copy (Text, CurPos, Editor.CellToCharIdx (TextCell (I + 1, 1)) - CurPos)) > 0 then
+									InAsm := False;
+							end else begin
+								LineDone := False;
+								LastWord := '';
+								WordIndex := 0;
+								InSpace := True;
+								while (CurPos <= TextLength) and (not LineDone) do begin
+									case Text [CurPos] of
+										'A'..'Z', 'a'..'z', '0'..'9', '_', '$', ':': begin
+											if InSpace and (Text [CurPos] = '_') and (Copy (Text, CurPos, Length ('__attribute__')) = '__attribute__') then begin
+												Inc (CurPos, Length ('__attribute__'));
+												while (CurPos <= TextLength) and (Text [CurPos] in [#32, #9]) do
+													Inc (CurPos);
+												if (CurPos <= TextLength) and (Text [CurPos] = '(') then begin
+													Inc (CurPos);
+													J := 1;
+													while (CurPos <= TextLength) and (J > 0) do begin
+														case Text [CurPos] of
+															'(': Inc (J);
+															')': Dec (J);
+														end;
+														Inc (CurPos);
+													end;
+												end else
+													Dec (CurPos);
+											end else begin
+												if InSpace then begin
+													LastWord := '';
+													InSpace := False;
+													Inc (WordIndex);
+												end;
+												LastWord := LastWord + Text [CurPos];
+												if WordIndex <= 1 then
+													FirstWord := LastWord;
+											end;
+										end;
+										#32, #9, #0, '*', '&': begin
+											InSpace := True;
+											if (Pos (':', LastWord) > 0) and (Pos ('::', LastWord) <= 0) then
+												LineDone := True;
+										end;
+										'#': begin
+											InCompSM := True;
+											LineDone := True;
+										end;
+										else
+											LineDone := True;
+									end;
+									Inc (CurPos);
+								end;
+								if (WordIndex >= 2) and (WordIndex <= 4) and (CurPos - 1 <= TextLength) and (Text [CurPos - 1] = '(') and (((FirstWord <> 'struct') and (FirstWord <> 'union') and (FirstWord <> 'enum')) or (WordIndex > 2)) then begin
+									while (CurPos <= TextLength) and (Text [CurPos] <> ')') do
+										Inc (CurPos);
+									Inc (CurPos);
+									if (CurPos <= TextLength) and (Text [CurPos] <> '(') then begin
+										LineDone := (CurPos <= TextLength) and (Text [CurPos] = ';');
+										if not LineDone then begin
+											J := CurPos;
+											while (J <= TextLength) and (not (Text [J] in [';', '{', '=', #13, #10])) do
+												Inc (J);
+											if (J <= TextLength) and (Text [J] = ';') then
+												LineDone := True;
+										end;
+										if LineDone then
+											for J := Low (Result) to High (Result) do
+												if Result[J].Name = LastWord then begin
+													LineDone := False;
+													Break;
+												end;
+										if LineDone then begin
+											SetLength (Result, Length (Result) + 1);
+											with Result [High (Result)] do begin
+												Name := LastWord;
+												PrototypeLine := I;
+												ImplementationLine := 0;
+											end;
+										end else begin
+											for J := Low (Result) to High (Result) do
+												if Result[J].Name = LastWord then begin
+													Result[J].ImplementationLine := I;
+													InFunc := True;
+													LineDone := True;
+													Break;
+												end;
+											if not LineDone then begin
+												while (CurPos <= TextLength) and (not (Text [CurPos] in ['{', ';', '='])) do
+													Inc (CurPos);
+												if (CurPos <= TextLength) and (Text [CurPos] <> '=') then begin
+													SetLength (Result, Length (Result) + 1);
+													with Result [High (Result)] do begin
+														Name := LastWord;
+														PrototypeLine := 0;
+														ImplementationLine := I;
+														InFunc := True;
+													end;
+												end;
+											end;
+										end;
+									end;
+								end;
+							end;
+						end;
+					end;
+				end;
+			end;
+		ftGNUAsmFile, ftA68kAsmFile:
+			for I := 1 to Editor.LineCount do begin
+				CurPos := Editor.CellToCharIdx (TextCell (I, 1));
+				LineDone := False;
+				LastWord := '';
+				while (CurPos <= TextLength) and (not LineDone) do begin
+					if Text [CurPos] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'] then
+						LastWord := LastWord + Text [CurPos]
+					else
+						LineDone := True;
+					Inc (CurPos);
+				end;
+				if (CurPos - 1 <= TextLength) and (Text [CurPos - 1] = ':') then begin
+					SetLength (Result, Length (Result) + 1);
+					with Result [High (Result)] do begin
+						Name := LastWord;
+						PrototypeLine := 0;
+						ImplementationLine := I;
+					end;
+				end;
+			end;
+	end;
+end;
+
+function TSourceTextSourceFile.GetInternalTextEditor: TMemoComponent;
+begin
+	Result := FEditor;
+end;
+
+function TSourceTextSourceFile.GetSourceEditor: TSourceEdit;
+begin
+	if not Assigned (FEditor) then begin
+		FEditor := TSourceEdit.Create (Application.MainForm);
+		with FEditor do begin
+			AllowUndo := False;
+			Text := FTempContent;
+		end;
+		UpdateEditor;
+		UpdateSyntax;
+		FTempContent := '';
+		with FEditor do begin
+			OnChangePrivate := Change;
+			OnReplaceText := ReplaceText;
+			AllowUndo := True;
+		end;
+	end;
+	Result := FEditor;
+end;
+
+function TSourceTextSourceFile.GetTextEditor: TMemoComponent;
+begin
+	Result := SourceEditor;
+end;
+
+procedure TSourceTextSourceFile.SplitAndWriteToFile(const FN: string);
+type
+	TCharMode = (cmNone, cmNormalText, cmNumber, cmMultiSymbol, cmString, cmChar, cmComment, cmUnchangableLine, cmExtUnchangableLine, cmTrigraph);
+var
+	S: string;
+{$IFDEF CanSplit}
+	C: Char;
+	CurPos: Integer;
+	CurMode: TCharMode;
+	AtLineStart: Boolean;
+	Stream: TStream;
+procedure InsertChar(Ch: Char);
+begin
+	Stream.Write (Ch, SizeOf (Char));
+end;
+procedure InsertString(const Str: string);
+begin
+	Stream.Write (PChar(Str)^, Length (Str));
+end;
+procedure AddLine(Offset: Integer = 0);
+begin
+	LineStartList.Add (CurPos + Offset);
+	AtLineStart := True;
+end;
+procedure NewLine;
+begin
+	if (not (AtLineStart or (Copy (S, CurPos, 1) = #13))) or (Copy (S, CurPos, 1) = '#') then begin
+		InsertString (#13#10);
+		AddLine;
+	end;
+	CurMode := cmNone;
+end;
+procedure SetMultiCharMode(Mode: TCharMode);
+begin
+	if CurMode <> Mode then begin
+		NewLine;
+		CurMode := Mode;
+	end;
+end;
+var
+	I: Integer;
+	B,
+	NoInsert: Boolean;
+{$ENDIF}
+begin
+	try
+{$IFDEF CanSplit}
+		if SplitFiles then begin
+			case ContentType of
+				ftCFile: begin
+					if not Assigned (LineStartList) then
+						LineStartList := TIntegerList.Create;
+					LineStartList.Clear;
+					LineStartList.Add (1);
+					CurPos := 1;
+					AddLine;
+					AtLineStart := True;
+					S := Content;
+					CreatePathFor (FN);
+					Stream := TFileStream.Create (FN, fmCreate or fmShareExclusive);
+					try
+						for CurPos := 1 to Length (S) do begin
+							NoInsert := False;
+							C := S [CurPos];
+							if C = #13 then
+								AddLine (2);
+							case CurMode of
+								cmString:
+									if (C = '"') then begin
+										B := True;
+										I := CurPos - 1;
+										while (I >= 1) and ((S [I] = '\') or (Copy (S, I - 2, 3) = '??/')) do begin
+											B := not B;
+											if S [I] = '\' then
+												Dec (I)
+											else
+												Dec (I, 3);
+										end;
+										if B then begin
+											CurMode := cmNone;
+											NoInsert := True;
+											InsertString (C + #13#10);
+											AtLineStart := True;
+											AddLine (1);
+										end;
+									end;
+								cmChar:
+									if (C = '''') then begin
+										B := True;
+										I := CurPos - 1;
+										while (I >= 1) and ((S [I] = '\') or (Copy (S, I - 2, 3) = '??/')) do begin
+											B := not B;
+											if S [I] = '\' then
+												Dec (I)
+											else
+												Dec (I, 3);
+										end;
+										if B then
+											CurMode := cmNone;
+									end;
+								cmComment: begin
+									if (C = '/') and (S [CurPos - 1] = '*') then
+										CurMode := cmNone;
+								end;
+								cmUnchangableLine:
+									if C = #13 then
+										CurMode := cmNone;
+								cmExtUnchangableLine:
+									if (C = #13) and (S [CurPos - 1] <> '\') then
+										CurMode := cmNone;
+								cmTrigraph:
+									if (C <> '?') and ((CurPos + 1 > Length (S)) or (S [CurPos + 1] <> '?')) then
+										CurMode := cmNone;
+								else begin
+									if Copy (S, CurPos, 2) = '//' then
+										SetMultiCharMode (cmUnchangableLine)
+									else if Copy (S, CurPos, 2) = '/*' then
+										SetMultiCharMode (cmComment)
+									else if Copy (S, CurPos, 2) = '??=' then
+										SetMultiCharMode (cmExtUnchangableLine)
+									else if (Copy (S, CurPos, 2) = '??') and (Length (S) >= CurPos + 2) and (S [CurPos + 2] in ['(', ')', '/', '''', '<', '>', '!', '-']) then
+										SetMultiCharMode (cmTrigraph)
+									else
+										case C of
+											#32, #9:
+												if (CurPos > 1) and (not (S [CurPos - 1] in [#32, #9])) then
+													NewLine;
+											'A'..'Z', 'a'..'z', '0'..'9', '_', '$':
+												if not (CurMode in [cmNormalText, cmNumber]) then begin
+													NewLine;
+													if C in ['0'..'9'] then
+														CurMode := cmNumber
+													else
+														CurMode := cmNormalText;
+												end;
+											'"':
+												SetMultiCharMode (cmString);
+											'''':
+												SetMultiCharMode (cmChar);
+											'#':
+												SetMultiCharMode (cmExtUnchangableLine);
+											'.':
+												if CurMode <> cmNumber then begin
+													if (Length (S) >= CurPos + 1) and (S [CurPos + 1] in ['0'..'9']) then begin
+														NewLine;
+														CurMode := cmNumber;
+													end else
+														SetMultiCharMode (cmMultiSymbol);
+												end;
+											'+', '-':
+												if (CurMode <> cmNumber) or (CurPos - 1 <= 1) or (not (S [CurPos - 1] in ['e', 'E', 'p', 'P'])) then
+													SetMultiCharMode (cmMultiSymbol);
+											else
+												if C in CSingleSymbols then begin
+													if CurMode <> cmNone then begin
+														NewLine;
+														CurMode := cmNone;
+													end;
+													if (CurPos + 1 <= Length (S)) and (S [CurPos + 1] <> #13) then begin
+														NoInsert := True;
+														InsertString (C + #13#10);
+														AddLine (1);
+													end;
+												end else
+													SetMultiCharMode (cmMultiSymbol);
+										end;
+								end;
+							end;
+							if not NoInsert then begin
+								InsertChar (C);
+								if not (C in [#13, #10]) then
+									AtLineStart := False;
+							end;
+						end;
+						NewLine;
+					finally
+						Stream.Free;
+					end;
+				end;
+				else
+					WriteToFile (FN);
+			end;
+		end else
+{$ENDIF}
+		begin
+			S := Content;
+			CreatePathFor (FN);
+			with TFileStream.Create (FN, fmCreate or fmShareExclusive) do try
+				Write (PChar(S)^, Length (S));
+				if ContentType = ftCFile then
+					Write (PChar(#13#10)^, 2);
+			finally
+				Free;
+			end;
+		end;
+	except
+		ShowDefaultMessageBox ('Error writing temporary source file.', 'Error', mtProgramError);
+	end;
+end;
+
+procedure TSourceTextSourceFile.UpdateEditor;
+begin
+	inherited;
+	if Assigned (SourceEditor) then
+		with SourceEditor do
+			SplitOnFly := EditorOnFly;
+end;
+
+{ TCSourceFile }
+
+procedure TCSourceFile.Compile;
+var
+	Folder,
+	Switches: string;
+begin
+	CompStartFile;
+	OperationCancelled := False;
+	OperationSuccessful := False;
+	if FileExists (WithBackslash (TIGCCFolder) + GCCLocation + 'GCC.exe') then begin
+		CompSetMessage ('Compiling File ''' + SourceName + '''');
+		Folder := WithBackslash (Temp + FolderPath);
+		CurErrFunction := '';
+		InAssemblingState := False;
+		if FileExists (Folder + 'TEMPPROG.S') then
+			DeleteFile (Folder + 'TEMPPROG.S');
+		if FileExists (Temp + 'TEMPPROG.O') then
+			DeleteFile (Temp + 'TEMPPROG.O');
+		SplitAndWriteToFile (Folder + 'TEMPPROG.C');
+		MainConsole.Title := 'Compiler';
+		Switches := DefaultGCCSwitches + ' ' + GCCSwitches + ' ' + SpecialSwitches;
+		if UseDataVar then
+			Switches := Switches + ' -mno-merge-sections';
+		if AssumeUndefined then
+			Switches := Switches + ' -Werror-implicit-function-declaration';
+		if DebugInfo then
+			Switches := Switches + ' -gcoff -mcoff-abslines';
+		if ProjectTarget = ptFargo then
+			Switches := Switches + ' -DFARGO'
+		else if ProjectTarget = ptFlashOS then
+			Switches := Switches + ' -DFLASH_OS'
+		else if Assigned (PredefinedLibOptions) and (ProjectTarget = ptRegular) then
+			Switches := Switches + ' ' + PredefinedLibOptions.GetSwitches;
+		CompUpdate;
+		try
+			MainConsole.StartProcess (WithBackslash (TIGCCFolder) + GCCLocation + 'GCC.exe', '-S -I ' + Folder + ' ' + Switches + ' "' + Folder + 'tempprog.c" -o "' + Folder + 'tempprog.s"', WithoutBackslash (WithBackslash (TIGCCFolder) + GCCLocation));
+			WaitForMainConsole ('Compilation');
+		except
+			ShowDefaultMessageBox ('Could not start compiler.', 'Error', mtProgramError);
+		end;
+		OperationSuccessful := True;
+		ProcessErrors (MainConsole.LastErrText);
+		if OperationSuccessful then begin
+			OperationSuccessful := False;
+			if not OperationCancelled then
+				if FileExists (Folder + 'TEMPPROG.S') then begin
+					OperationSuccessful := True;
+					ProcessSFile (Folder + 'TEMPPROG.S', ChangeFileExt (FileName, '.s'));
+				end;
+		end;
+		if OperationSuccessful then begin
+			OperationSuccessful := False;
+			CurErrFunction := '';
+			InAssemblingState := True;
+			CompUpdate;
+			Switches := DefaultAsSwitches + ' ' + AsSwitches;
+			if CutUnusedRanges or (ProjectTarget = ptArchive) then
+				Switches := Switches + ' --all-relocs';
+			if OptimizeReturns or (ProjectTarget = ptArchive) then
+				Switches := Switches + ' --keep-locals';
+			try
+				MainConsole.StartProcess (WithBackslash (TIGCCFolder) + AsLocation + 'As.exe', '-I ' + Folder + ' ' + Switches + ' "' + Folder + 'tempprog.s" -o ' + Temp + 'tempprog.o', WithoutBackslash (WithBackslash (TIGCCFolder) + AsLocation));
+				WaitForMainConsole ('Compilation');
+			except
+				ShowDefaultMessageBox ('Could not start assembler.', 'Error', mtProgramError);
+			end;
+			if FileExists (Temp + 'TEMPPROG.O') then begin
+				if not OperationCancelled then begin
+					CopyFile (PChar (Temp + 'TEMPPROG.O'), PChar (ChangeFileExt (FileName, '.o')), False);
+					OperationSuccessful := True;
+				end;
+				DeleteFile (Temp + 'TEMPPROG.O');
+			end;
+			ProcessErrors (MainConsole.LastErrText);
+		end;
+		SFileClear;
+		CompUpdate;
+		try
+			if FileExists (Folder + 'TEMPPROG.C') then
+				DeleteFile (Folder + 'TEMPPROG.C');
+			if FileExists (Folder + 'TEMPPROG.S') then
+				DeleteFile (Folder + 'TEMPPROG.S');
+			RemovePath (Folder, Temp);
+		except end;
+		CompUpdate;
+	end else
+		ShowDefaultMessageBox ('Cannot find compiler.', 'Error', mtProgramError);
+	if OperationSuccessful and not OperationCancelled then
+		Invalidated := False;
+end;
+
+destructor TCSourceFile.Destroy;
+begin
+	SFileClear;
+	inherited;
+end;
+
+class function TCSourceFile.GetClassFilter: string;
+begin
+	Result := 'C Files (*.c)|*.c';
+end;
+
+class function TCSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 4;
+end;
+
+class function TCSourceFile.GetClassItemName: string;
+begin
+	Result := 'C File';
+end;
+
+class function TCSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 1;
+end;
+
+class function TCSourceFile.GetCompilable: Boolean;
+begin
+	Result := True;
+end;
+
+function TCSourceFile.GetContentType: TSourceFileType;
+begin
+	Result := ftCFile;
+end;
+
+procedure TCSourceFile.ProcessErrorLine(Line: string);
+var
+	Whole: string;
+	P,
+	Ofs: Integer;
+	S: string;
+	FN: string;
+	Tp: TBugType;
+	CurErrFile: string;
+begin
+	if not Assigned (OnError) then
+		Exit;
+	P := Pos (#10, Line);
+	if P > 0 then begin
+		ProcessErrorLine (Copy (Line, 1, P - 1));
+		ProcessErrorLine (Copy (Line, P + 1, Length (Line)));
+	end else begin
+		repeat
+			P := Pos ('`', Line);
+			if P > 0 then
+				Line [P] := '''';
+		until P <= 0;
+		repeat
+			P := Pos ('´', Line);
+			if P > 0 then
+				Line [P] := '''';
+		until P <= 0;
+		repeat
+			P := Pos ('"', Line);
+			if P > 0 then
+				Line [P] := '''';
+		until P <= 0;
+		Line := Trim (Line);
+		if (Pos ('ASSEMBLER MESSAGES:', UpperCase (Line)) > 0) or
+			StartsWith ('FROM ', Line) or
+			(AssumeUndefined and
+			((Pos ('PREVIOUS IMPLICIT DECLARATION', UpperCase (Line)) > 0) or
+			(Pos ('PREVIOUSLY IMPLICITLY DECLARED', UpperCase (Line)) > 0))) then
+			Exit;
+		Whole := Line;
+		FN := '';
+		CurErrFile := '';
+		if StartsWith ('IN FILE', Line) then
+			CurErrFunction := ''
+		else begin
+			P := Pos (':', Line);
+			while (P > 0) and (Length (Line) > P) and (Line [P + 1] in ['\', '/']) do begin
+				Ofs := Pos (':', Copy (Line, P + 1, Length (Line)));
+				if Ofs > 0 then
+					Inc (P, Ofs)
+				else begin
+					P := 0;
+					Break;
+				end;
+			end;
+			if P > 0 then
+				FN := Copy (Line, 1, P - 1);
+			if Length (FN) > 0 then begin
+				Delete (Line, 1, Length (FN) + 1);
+				repeat
+					P := Pos ('/', FN);
+					if P > 0 then
+						FN [P] := '\';
+				until P <= 0;
+				if InAssemblingState then begin
+					if Pos ('TEMPPROG', UpperCase (FN)) > 0 then
+						CurErrFile := ChangeFileExt (FileName, '.s')
+					else
+						CurErrFile := ExtractFileName (FN);
+				end else begin
+					if UpperCase (ExtractFileExt (FN)) = '.S' then begin
+						FN := '';
+						CurErrFunction := '';
+					end else begin
+						if Pos ('TEMPPROG', UpperCase (FN)) > 0 then
+							CurErrFile := FileName
+						else
+							CurErrFile := ExtractFileName (FN);
+					end;
+				end;
+				P := 0;
+				Ofs := 0;
+				if (Length (Line) > 0) and (Line [1] in ['0'..'9']) then begin
+					try
+						S := Copy (Line, 1, Pos (':', Line) - 1);
+						P := StrToInt (S);
+						if InAssemblingState then
+							SFileMapLine (P);
+						Delete (Line, 1, Length (S) + 1);
+						if (Length (Line) > 0) and (Line [1] in ['0'..'9']) then try
+							S := Copy (Line, 1, Pos (':', Line) - 1);
+							Ofs := StrToInt (S) - 1;
+							Delete (Line, 1, Length (S) + 1);
+						except end;
+					except end;
+					Line := Trim (Line);
+					if StartsWith ('WARNING:', Line, False, True) then
+						Tp := btWarning
+					else begin
+						StartsWith ('ERROR:', Line, False, True);
+						Tp := btError;
+						OperationSuccessful := False;
+					end;
+					Line := Trim (Line);
+					if StartsWith ('#WARNING ', Line, False, True) then
+						Tp := btWarning;
+					StartsWith ('#ERROR ', Line, False, True);
+					if StartsWith ('PREVIOUS DECLARATION OF ', Line) or
+						StartsWith ('POSSIBLE REAL START OF ', Line) or
+						StartsWith ('UNUSED VARIABLE ', Line) or
+						StartsWith ('UNUSED PARAMETER ', Line) or
+						(Pos ('PREVIOUSLY DECLARED HERE', UpperCase (Line)) > 0) or
+						(Pos ('LOCATION OF THE PREVIOUS DEFINITION', UpperCase (Line)) > 0) then
+						Tp := btInfo;
+					if AssumeUndefined and StartsWith ('Implicit declaration of ', Line, False, True) then begin
+						Insert ('Undefined reference to ', Line, 1);
+						Tp := btError;
+						OperationSuccessful := False;
+					end;
+					if (Length (CurErrFile) <= 0) and (P > 0) and (Length (FN) > 0) then
+						Line := UpperCase (ExtractFileName (FN)) + ' Line ' + IntToStr (P) + ' - ' + Line;
+					Line := Trim (Line);
+					if (Length (Line) > 0) and (Line [Length (Line)] <> '.') then
+						Line := Line + '.';
+					OnError (Whole, Tp, CurErrFile, CurErrFunction, Line, P, Ofs);
+					if Tp = btError then
+						OperationSuccessful := False;
+				end else begin
+					if StartsWith (' IN FUNCTION ''', Line, False, True) then
+						CurErrFunction := Copy (Line, 1, Pos ('''', Line) - 1)
+					else if StartsWith (' AT TOP LEVEL', Line) then
+						CurErrFunction := ''
+					else
+						OnError (Whole, btError, FileName, '', Line, 0, 0);
+				end;
+			end else begin
+				Tp := btError;
+				if StartsWith ('PLEASE FILL OUT ', Line) then
+					Tp := btInfo;
+				OnError (Whole, Tp, '', '', Whole, 0, 0);
+			end;
+		end;
+	end;
+end;
+
+procedure TCSourceFile.ProcessSFile(const SourceFile, DestFile: string);
+var
+	L: TStringList;
+begin
+	L := TStringList.Create;
+	with L do try
+		LoadFromFile (SourceFile);
+		if (Count > 0) and (Copy (LowerCase (Strings [0]), 1, Length (#9'.file')) = #9'.file') then
+			Strings [0] := #9'.file'#9'"' + ExtractFileName (FileName) + '"';
+		try
+			ParseSFile (L);
+		except
+			OperationSuccessful := False;
+		end;
+		SaveToFile (SourceFile);
+		if DebugInfo then
+			ParseDebugSFile (L, SFileLineChange, nil, GetLineContents);
+		SaveToFile (DestFile);
+	finally
+		Free;
+	end;
+end;
+
+procedure TCSourceFile.Save;
+var
+	FH: THandle;
+begin
+	inherited;
+	if (not Invalidated) and FileExists (ChangeFileExt (FileName, '.o')) then begin
+		FH := FileOpen (ChangeFileExt (FileName, '.o'), fmOpenReadWrite + fmShareExclusive);
+		FileSetDate (FH, FileAge (FileName));
+		FileClose (FH);
+	end;
+end;
+
+procedure TCSourceFile.SetModified(const Value: Boolean);
+begin
+	if not Modifying then begin
+		Modifying := True;
+		FModified := Value;
+		if Value then
+			Invalidate;
+		Modifying := False;
+	end;
+end;
+
+procedure TCSourceFile.SFileClear;
+begin
+	if Assigned (FSFileChangedLines) then
+		FSFileChangedLines.Free;
+	if Assigned (FSFileLineChanges) then
+		FSFileLineChanges.Free;
+	FSFileChangedLines := nil;
+	FSFileLineChanges := nil;
+end;
+
+procedure TCSourceFile.SFileLineChange(StartLine, Change: Integer);
+begin
+	if not Assigned (FSFileChangedLines) then
+		FSFileChangedLines := TIntegerList.Create;
+	if not Assigned (FSFileLineChanges) then
+		FSFileLineChanges := TIntegerList.Create;
+	FSFileChangedLines.Add (StartLine);
+	FSFileLineChanges.Add (Change);
+end;
+
+procedure TCSourceFile.SFileMapLine(var Line: Integer);
+var
+	I: Integer;
+begin
+	if Assigned (FSFileChangedLines) and Assigned (FSFileLineChanges) then
+		for I := 0 to FSFileChangedLines.Count - 1 do
+			if Line > FSFileChangedLines.Items [I] then
+				Inc (Line, FSFileLineChanges.Items [I]);
+end;
+
+procedure TCSourceFile.UpdateEditor;
+begin
+	inherited;
+	if Assigned (SourceEditor) then begin
+		SourceEditor.TabSize := TabSizeC;
+		SourceEditor.AutoIndentIncrease := AutoBlocks;
+	end;
+end;
+
+procedure TCSourceFile.UpdateSyntax;
+begin
+	if Assigned (SourceEditor) then
+		with SourceEditor do
+			SyntaxColoring.Assign (SyntaxC);
+end;
+
+{ TGNUAsmSourceFile }
+
+procedure TGNUAsmSourceFile.Compile;
+var
+	Folder,
+	Switches: string;
+begin
+	CompStartFile;
+	OperationCancelled := False;
+	OperationSuccessful := False;
+	if FileExists (WithBackslash (TIGCCFolder) + AsLocation + 'As.exe') then begin
+		CompSetMessage ('Assembling File ''' + SourceName + '''');
+		Folder := WithBackslash (Temp + FolderPath);
+		if FileExists (Temp + 'TEMPPROG.O') then
+			DeleteFile (Temp + 'TEMPPROG.O');
+		SplitAndWriteToFile (Folder + 'TEMPPROG.S');
+		Switches := DefaultAsSwitches + ' ' + AsSwitches;
+		if CutUnusedRanges or (ProjectTarget = ptArchive) then
+			Switches := Switches + ' --all-relocs';
+		if OptimizeReturns or (ProjectTarget = ptArchive) then
+			Switches := Switches + ' --keep-locals';
+		MainConsole.Title := 'Assembler';
+		try
+			MainConsole.StartProcess (WithBackslash (TIGCCFolder) + AsLocation + 'As.exe', '-I ' + Folder + ' ' + Switches + ' "' + Folder + 'tempprog.s" -o ' + Temp + 'tempprog.o', WithoutBackslash (WithBackslash (TIGCCFolder) + AsLocation));
+			WaitForMainConsole ('Assembling');
+		except
+			ShowDefaultMessageBox ('Could not start assembler.', 'Error', mtProgramError);
+		end;
+		if FileExists (Temp + 'TEMPPROG.O') then begin
+			if not OperationCancelled then begin
+				CopyFile (PChar (Temp + 'TEMPPROG.O'), PChar (ChangeFileExt (FileName, '.o')), False);
+				OperationSuccessful := True;
+			end;
+			DeleteFile (Temp + 'TEMPPROG.O');
+		end;
+		ProcessErrors (MainConsole.LastErrText);
+		try
+			if FileExists (Folder + 'TEMPPROG.S') then
+				DeleteFile (Folder + 'TEMPPROG.S');
+			RemovePath (Folder, Temp);
+		except end;
+		CompUpdate;
+	end else
+		ShowDefaultMessageBox ('Cannot find assembler.', 'Error', mtProgramError);
+	if OperationSuccessful and not OperationCancelled then
+		Invalidated := False;
+end;
+
+class function TGNUAsmSourceFile.GetClassFilter: string;
+begin
+	Result := 'GNU Assembly Files (*.s)|*.s';
+end;
+
+class function TGNUAsmSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 5;
+end;
+
+class function TGNUAsmSourceFile.GetClassItemName: string;
+begin
+	Result := 'GNU Assembler File';
+end;
+
+class function TGNUAsmSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 2;
+end;
+
+class function TGNUAsmSourceFile.GetCompilable: Boolean;
+begin
+	Result := True;
+end;
+
+function TGNUAsmSourceFile.GetContentType: TSourceFileType;
+begin
+	Result := ftGNUAsmFile;
+end;
+
+procedure TGNUAsmSourceFile.ProcessErrorLine(Line: string);
+var
+	Whole: string;
+	P,
+	Ofs: Integer;
+	S: string;
+	FN: string;
+	Tp: TBugType;
+	CurErrFile: string;
+begin
+	P := Pos (#10, Line);
+	if P > 0 then begin
+		ProcessErrorLine (Copy (Line, 1, P - 1));
+		ProcessErrorLine (Copy (Line, P + 1, Length (Line)));
+	end else begin
+		repeat
+			P := Pos ('`', Line);
+			if P > 0 then
+				Line [P] := '''';
+		until P <= 0;
+		repeat
+			P := Pos ('´', Line);
+			if P > 0 then
+				Line [P] := '''';
+		until P <= 0;
+		repeat
+			P := Pos ('"', Line);
+			if P > 0 then
+				Line [P] := '''';
+		until P <= 0;
+		if (Pos ('ASSEMBLER MESSAGES:', UpperCase (Line)) > 0) or
+			(Pos ('IN FILE', UpperCase (Line)) > 0) then
+			Exit;
+		Whole := Line;
+		FN := '';
+		CurErrFile := '';
+		P := Pos (':', Line);
+		while (Length (Line) > P) and (Line [P + 1] in ['\', '/']) do
+			Inc (P, Pos (':', Copy (Line, P + 1, Length (Line))));
+		FN := Copy (Line, 1, P - 1);
+		if Length (FN) > 0 then begin
+			Delete (Line, 1, Length (FN) + 1);
+			repeat
+				P := Pos ('/', FN);
+				if P > 0 then
+					FN [P] := '\';
+			until P <= 0;
+			if (UpperCase (ExtractFileExt (FN)) = '.C') or (Pos ('TEMPPROG', UpperCase (FN)) > 0) then
+				CurErrFile := FileName
+			else
+				CurErrFile := ExtractFileName (FN);
+			P := 0;
+			Ofs := 0;
+			if (Length (Line) > 0) and (Line [1] in ['0'..'9']) then begin
+				try
+					S := Copy (Line, 1, Pos (':', Line) - 1);
+					P := StrToInt (S);
+					Delete (Line, 1, Length (S) + 1);
+					if (Length (Line) > 0) and (Line [1] in ['0'..'9']) then try
+						S := Copy (Line, 1, Pos (':', Line) - 1);
+						Ofs := StrToInt (S) - 1;
+						Delete (Line, 1, Length (S) + 1);
+					except end;
+				except end;
+				Line := Trim (Line);
+				if StartsWith ('WARNING:', Line, False, True) then
+					Tp := btWarning
+				else begin
+					StartsWith ('ERROR:', Line, False, True);
+					Tp := btError;
+					OperationSuccessful := False;
+				end;
+				Line := Trim (Line);
+				if (Length (CurErrFile) <= 0) and (P > 0) and (Length (FN) > 0) then
+					Line := UpperCase (ExtractFileName (FN)) + ' Line ' + IntToStr (P) + ' - ' + Line;
+				if Assigned (OnError) then
+					OnError (Whole, Tp, CurErrFile, '', Line, P, Ofs);
+			end else begin
+				if Assigned (OnError) then
+					OnError (Whole, btError, FileName, '', Line, 0, 0);
+			end;
+		end else
+			if Assigned (OnError) then
+				OnError (Whole, btError, '', '', Whole, 0, 0);
+	end;
+end;
+
+procedure TGNUAsmSourceFile.Save;
+var
+	FH: THandle;
+begin
+	inherited;
+	if (not Invalidated) and FileExists (ChangeFileExt (FileName, '.o')) then begin
+		FH := FileOpen (ChangeFileExt (FileName, '.o'), fmOpenReadWrite + fmShareExclusive);
+		FileSetDate (FH, FileAge (FileName));
+		FileClose (FH);
+	end;
+end;
+
+procedure TGNUAsmSourceFile.SetModified(const Value: Boolean);
+begin
+	if not Modifying then begin
+		Modifying := True;
+		FModified := Value;
+		if Value then
+			Invalidate;
+		Modifying := False;
+	end;
+end;
+
+procedure TGNUAsmSourceFile.UpdateEditor;
+begin
+	inherited;
+	if Assigned (SourceEditor) then begin
+		SourceEditor.TabSize := TabSizeAsm;
+		SourceEditor.AutoIndentIncrease := False;
+	end;
+end;
+
+procedure TGNUAsmSourceFile.UpdateSyntax;
+begin
+	if Assigned (SourceEditor) then
+		with SourceEditor do begin
+			SyntaxColoring.Assign (SyntaxAsmGNU);
+			TabSize := TabSizeAsm;
+			AutoIndentIncrease := False;
+		end;
+end;
+
+{ TAsmSourceFile }
+
+procedure TAsmSourceFile.Compile;
+var
+	Folder,
+	Switches: string;
+	FPos: Integer;
+	CurErrFile,
+	S: string;
+	CurErrLine,
+	P: Integer;
+	EmptyLn: Boolean;
+	LL: TStringList;
+begin
+	CompStartFile;
+	OperationCancelled := False;
+	OperationSuccessful := False;
+	if FileExists (WithBackslash (TIGCCFolder) + A68kLocation + 'A68k.exe') then begin
+		CompSetMessage ('Assembling File ''' + SourceName + '''');
+		Folder := WithBackslash (Temp + FolderPath);
+		if FileExists (WithBackslash (TIGCCFolder) + GCCLocation + 'TEMPPROG.O') then
+			DeleteFile (WithBackslash (TIGCCFolder) + GCCLocation + 'TEMPPROG.O');
+		if FileExists (Temp + 'TEMPPROG.O') then
+			DeleteFile (Temp + 'TEMPPROG.O');
+		SplitAndWriteToFile (Folder + 'TEMPPROG.ASM');
+		Switches := DefaultA68kSwitches + ' ' + AsmSwitches;
+		if CutUnusedRanges or (ProjectTarget = ptArchive) then
+			Switches := Switches + ' -a';
+		if OptimizeReturns or (ProjectTarget = ptArchive) then
+			Switches := Switches + ' -d';
+		MainConsole.Title := 'Assembler';
+		try
+			MainConsole.StartProcess (WithBackslash (TIGCCFolder) + A68kLocation + 'A68k.exe', '"' + Folder + 'tempprog.asm" ' + Switches, WithoutBackslash (Temp));
+			WaitForMainConsole ('Assembling');
+		except
+			ShowDefaultMessageBox ('Could not start assembler.', 'Error', mtProgramError);
+		end;
+		UpdateProgramOutput;
+		if not OperationCancelled then begin
+			if Assigned (ErrorList) then
+				ErrorList.Items.BeginUpdate;
+			try
+				LL := TStringList.Create;
+				try
+					LL.Text := MainConsole.LastOutText;
+					EmptyLn := False;
+					FPos := 0;
+					while FPos < LL.Count do begin
+						S := LL [FPos];
+						Inc (FPos);
+						CurErrLine := 0;
+						if (Length (S) <= 0) or (Pos ('ASSEMBLING', UpperCase (S)) > 0) then
+							EmptyLn := True
+						else begin
+							if EmptyLn then begin
+								EmptyLn := False;
+								while (FPos < LL.Count) and (Pos ('TEMPPROG.ASM LINE ', UpperCase (S)) <= 0) do begin
+									if (Length (S) > 0) and (Pos ('(USER MACRO)', UpperCase (S)) <= 0) then begin
+										if Length (CurErrFile) <= 0 then begin
+											while Pos ('/', S) > 0 do
+												S [Pos ('/', S)] := '\';
+											P := Pos ('LINE ', UpperCase (S));
+											if P > 0 then begin
+												CurErrFile := ExtractFileName (Copy (S, 1, P - 2));
+												try
+													CurErrLine := StrToInt (Copy (S, P + Length ('LINE '), Length (S)));
+												except
+													CurErrLine := 0;
+												end;
+											end;
+										end;
+									end;
+									S := LL [FPos];
+									Inc (FPos);
+								end;
+								if FPos < LL.Count then begin
+									if Length (CurErrFile) <= 0 then begin
+										Delete (S, 1, Pos ('TEMPPROG.ASM LINE ', UpperCase (S)) + Length ('TEMPPROG.ASM LINE ') - 1);
+										try
+											CurErrLine := StrToInt (S);
+										except
+											CurErrLine := 0;
+										end;
+									end;
+									Inc (FPos);
+									if FPos < LL.Count then begin
+										S := LL [FPos];
+										Inc (FPos);
+										S := Copy (S, FirstNonWhiteSpace (S), Length (S));
+										StartsWith ('^ ', S, True, True);
+										if S [Length (S)] = '.' then
+											Delete (S, Length (S), 1);
+										OperationSuccessful := False;
+										if Length (CurErrFile) <= 0 then
+											CurErrFile := FileName;
+										if Assigned (OnError) then
+											OnError (IntToStr (CurErrLine) + ': ' + S, btError, CurErrFile, '', S, CurErrLine, 0);
+										CurErrFile := '';
+									end;
+								end;
+							end;
+						end;
+					end;
+				except end;
+				LL.Free;
+			finally
+				if Assigned (ErrorList) then
+					ErrorList.Items.EndUpdate;
+			end;
+		end;
+		CompUpdate;
+		if FileExists (Temp + 'TEMPPROG.O') then begin
+			if not OperationCancelled then begin
+				CopyFile (PChar (Temp + 'TEMPPROG.O'), PChar (ChangeFileExt (FileName, '.o')), False);
+				OperationSuccessful := True;
+			end;
+			DeleteFile (Temp + 'TEMPPROG.O');
+		end;
+		try
+			if FileExists (Folder + 'TEMPPROG.ASM') then
+				DeleteFile (Folder + 'TEMPPROG.ASM');
+			RemovePath (Folder, Temp);
+		except end;
+		CompUpdate;
+	end else
+		ShowDefaultMessageBox ('Cannot find assembler.', 'Error', mtProgramError);
+	if OperationSuccessful and not OperationCancelled then
+		Invalidated := False;
+end;
+
+class function TAsmSourceFile.GetClassFilter: string;
+begin
+	Result := 'A68k Assembly Files (*.asm)|*.asm';
+end;
+
+class function TAsmSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 5;
+end;
+
+class function TAsmSourceFile.GetClassItemName: string;
+begin
+	Result := 'Assembler File';
+end;
+
+class function TAsmSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 3;
+end;
+
+class function TAsmSourceFile.GetCompilable: Boolean;
+begin
+	Result := True;
+end;
+
+function TAsmSourceFile.GetContentType: TSourceFileType;
+begin
+	Result := ftA68kAsmFile;
+end;
+
+procedure TAsmSourceFile.Save;
+var
+	FH: THandle;
+begin
+	inherited;
+	if (not Invalidated) and FileExists (ChangeFileExt (FileName, '.o')) then begin
+		FH := FileOpen (ChangeFileExt (FileName, '.o'), fmOpenReadWrite + fmShareExclusive);
+		FileSetDate (FH, FileAge (FileName));
+		FileClose (FH);
+	end;
+end;
+
+procedure TAsmSourceFile.SetModified(const Value: Boolean);
+begin
+	if not Modifying then begin
+		Modifying := True;
+		FModified := Value;
+		if Value then
+			Invalidate;
+		Modifying := False;
+	end;
+end;
+
+procedure TAsmSourceFile.UpdateEditor;
+begin
+	inherited;
+	if Assigned (SourceEditor) then begin
+		SourceEditor.TabSize := TabSizeAsm;
+		SourceEditor.AutoIndentIncrease := False;
+	end;
+end;
+
+procedure TAsmSourceFile.UpdateSyntax;
+begin
+	if Assigned (SourceEditor) then
+		with SourceEditor do begin
+			SyntaxColoring.Assign (SyntaxAsm);
+			TabSize := TabSizeAsm;
+			AutoIndentIncrease := False;
+		end;
+end;
+
+{ TQuillSourceFile }
+
+procedure TQuillSourceFile.Compile;
+var
+	QuillDrv: string;
+begin
+	QuillDrv := WithBackslash (TIGCCFolder) + QuillIncludeLocation + 'Quill.drv';
+	if not FileExists (QuillDrv) then begin
+		QuillDrv := WithBackslash (TIGCCFolder) + CIncludeLocation + 'Quill.drv';
+		if not FileExists (QuillDrv) then begin
+			QuillDrv := WithBackslash (TIGCCFolder) + GCCLocation + 'Quill.drv';
+			if not FileExists (QuillDrv) then
+				QuillDrv := 'Quill.drv';
+		end;
+	end;
+	SpecialSwitches := SpecialQuillGCCSwitches + ' -include "' + QuillDrv + '"';
+	inherited;
+end;
+
+class function TQuillSourceFile.GetClassFilter: string;
+begin
+	Result := 'Quill Files (*.qll)|*.qll';
+end;
+
+class function TQuillSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 4;
+end;
+
+class function TQuillSourceFile.GetClassItemName: string;
+begin
+	Result := 'Quill File';
+end;
+
+class function TQuillSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 3;
+	if ssA68k in SpecialSupport then
+		Inc (Result);
+end;
+
+function TQuillSourceFile.GetContentType: TSourceFileType;
+begin
+	Result := ftQuillFile;
+end;
+
+procedure TQuillSourceFile.UpdateSyntax;
+begin
+	if Assigned (SourceEditor) then
+		with SourceEditor do
+			SyntaxColoring.Assign (SyntaxQuill);
+end;
+
+{ TObjectSourceFile }
+
+class function TObjectSourceFile.GetClassFilter: string;
+begin
+	Result := 'Object Files (*.o)|*.o';
+end;
+
+class function TObjectSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 6;
+end;
+
+class function TObjectSourceFile.GetClassItemName: string;
+begin
+	Result := 'Object File';
+end;
+
+class function TObjectSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 3;
+	if ssA68k in SpecialSupport then
+		Inc (Result);
+	if ssQuill in SpecialSupport then
+		Inc (Result);
+end;
+
+{ TArchiveSourceFile }
+
+class function TArchiveSourceFile.GetClassFilter: string;
+begin
+	Result := 'Archive Files (*.a)|*.a';
+end;
+
+class function TArchiveSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 6;
+end;
+
+class function TArchiveSourceFile.GetClassItemName: string;
+begin
+	Result := 'Archive File';
+end;
+
+class function TArchiveSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 4;
+	if ssA68k in SpecialSupport then
+		Inc (Result);
+	if ssQuill in SpecialSupport then
+		Inc (Result);
+end;
+
+{ TNormalTextSourceFile }
+
+destructor TNormalTextSourceFile.Destroy;
+var
+	PrevEditor: TMemoComponent;
+begin
+	if Assigned (FEditor) then begin
+		PrevEditor := FEditor;
+		FEditor := nil;
+		PrevEditor.Free;
+	end;
+	inherited;
+end;
+
+class function TNormalTextSourceFile.GetClassFilter: string;
+begin
+	Result := 'Text Files (*.txt)|*.txt';
+end;
+
+class function TNormalTextSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 7;
+end;
+
+class function TNormalTextSourceFile.GetClassItemName: string;
+begin
+	Result := 'Text File';
+end;
+
+class function TNormalTextSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 5;
+	if ssA68k in SpecialSupport then
+		Inc (Result);
+	if ssQuill in SpecialSupport then
+		Inc (Result);
+end;
+
+function TNormalTextSourceFile.GetInternalTextEditor: TMemoComponent;
+begin
+	Result := FEditor;
+end;
+
+function TNormalTextSourceFile.GetTextEditor: TMemoComponent;
+begin
+	if not Assigned (FEditor) then begin
+		FEditor := TMemoComponent.Create (Application.MainForm);
+		with FEditor do begin
+			AllowUndo := False;
+			TabSize := 8;
+			Text := FTempContent;
+		end;
+		UpdateEditor;
+		FTempContent := '';
+		with FEditor do begin
+			OnChangePrivate := Change;
+			OnReplaceText := ReplaceText;
+			AllowUndo := True;
+		end;
+	end;
+	Result := FEditor;
+end;
+
+{ TOtherSourceFile }
+
+class function TOtherSourceFile.GetClassFilter: string;
+begin
+	Result := '';
+end;
+
+class function TOtherSourceFile.GetClassImageIndex: Integer;
+begin
+	Result := 8;
+end;
+
+class function TOtherSourceFile.GetClassItemName: string;
+begin
+	Result := 'Other File';
+end;
+
+class function TOtherSourceFile.GetClassTreeIndex: Integer;
+begin
+	Result := 6;
+	if ssA68k in SpecialSupport then
+		Inc (Result);
+	if ssQuill in SpecialSupport then
+		Inc (Result);
+end;
+
+end.

BIN
tigcc/ide/SourceFileWinUnit.dfm


+ 789 - 0
tigcc/ide/SourceFileWinUnit.pas

@@ -0,0 +1,789 @@
+unit SourceFileWinUnit;
+
+interface
+
+uses
+	SourceFileUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  ComCtrls, Menus, ActnList, ToolWin, MemoComponentUnit, ExtCtrls{$IFDEF CODINGEXT}, CompletionForm{$ENDIF};
+
+type
+	TSourceFileForm = class(TForm)
+    Actions: TActionList;
+    ActionFilePrint: TAction;
+    ActionFilePrintQuickly: TAction;
+		ActionFileClose: TAction;
+		ActionEditUndo: TAction;
+    ActionEditRedo: TAction;
+    ActionEditDelete: TAction;
+    ActionEditCut: TAction;
+    ActionEditCopy: TAction;
+    ActionEditPaste: TAction;
+    ActionEditSelectAll: TAction;
+    ActionFindFind: TAction;
+    ActionFindReplace: TAction;
+    ActionFindOpenFile: TAction;
+    ActionFindFunctions: TAction;
+    ActionEditIncreaseIndent: TAction;
+    ActionEditDecreaseIndent: TAction;
+		MainMenu: TMainMenu;
+    File1: TMenuItem;
+		Print1: TMenuItem;
+    Edit1: TMenuItem;
+    Undo1: TMenuItem;
+    Redo1: TMenuItem;
+    N2: TMenuItem;
+    Delete1: TMenuItem;
+    Cut1: TMenuItem;
+    Copy1: TMenuItem;
+    Paste1: TMenuItem;
+    N9: TMenuItem;
+    SelectAll1: TMenuItem;
+    N18: TMenuItem;
+		IncreaseIndent1: TMenuItem;
+    DecreaseIndent1: TMenuItem;
+    Find1: TMenuItem;
+		Find2: TMenuItem;
+    Replace1: TMenuItem;
+    N13: TMenuItem;
+    Functions1: TMenuItem;
+    N15: TMenuItem;
+    OpenFileAtCursor1: TMenuItem;
+    ActionFileSave: TAction;
+    ActionFileSaveAs: TAction;
+    ActionFileCompile: TAction;
+    Save1: TMenuItem;
+    SaveAs1: TMenuItem;
+		N1: TMenuItem;
+		Compile1: TMenuItem;
+		N3: TMenuItem;
+		N4: TMenuItem;
+		Close1: TMenuItem;
+		StatusBar: TStatusBar;
+    EditorToolBar: TToolBar;
+    ToolButton3: TToolButton;
+    ToolButton4: TToolButton;
+    ToolButton23: TToolButton;
+    ToolButton24: TToolButton;
+    ToolButton6: TToolButton;
+    ToolButton7: TToolButton;
+    ToolButton8: TToolButton;
+		ToolButton9: TToolButton;
+    ToolButton10: TToolButton;
+    ToolButton5: TToolButton;
+    ToolButton19: TToolButton;
+    ToolButton11: TToolButton;
+		ToolButton20: TToolButton;
+    ToolButton21: TToolButton;
+    ToolButton25: TToolButton;
+    ToolButton22: TToolButton;
+    ToolButton13: TToolButton;
+    ToolBarBevel: TBevel;
+    ToolButton1: TToolButton;
+    EditorPopup: TPopupMenu;
+    Undo2: TMenuItem;
+		Redo2: TMenuItem;
+    N16: TMenuItem;
+    Clear1: TMenuItem;
+    Cut2: TMenuItem;
+    Copy2: TMenuItem;
+    Paste2: TMenuItem;
+		N17: TMenuItem;
+    SelectAll2: TMenuItem;
+    N20: TMenuItem;
+    IncreaseIndent2: TMenuItem;
+    DecreaseIndent2: TMenuItem;
+		N5: TMenuItem;
+		OpenFileatCursor2: TMenuItem;
+		FindDlg: TFindDialog;
+		ReplaceDlg: TReplaceDialog;
+		FunctionPopup: TPopupMenu;
+		NoFunctionsItem: TMenuItem;
+		ActionFileAddToProject: TAction;
+		AddtoProject1: TMenuItem;
+		N6: TMenuItem;
+		ToolButton2: TToolButton;
+		procedure FormClose(Sender: TObject; var Action: TCloseAction);
+		procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+		procedure FormCreate(Sender: TObject);
+		procedure ActionFileCloseExecute(Sender: TObject);
+		procedure FileSave(Sender: TObject);
+		procedure FileSaveAs(Sender: TObject);
+		procedure FileCompile(Sender: TObject);
+		procedure FilePrint(Sender: TObject);
+		procedure FilePrintQuickly(Sender: TObject);
+		procedure EditorChange(Sender: TObject);
+		procedure EditUndo(Sender: TObject);
+		procedure EditRedo(Sender: TObject);
+		procedure EditDelete(Sender: TObject);
+		procedure EditCut(Sender: TObject);
+		procedure EditCopy(Sender: TObject);
+		procedure EditPaste(Sender: TObject);
+		procedure EditSelectAll(Sender: TObject);
+		procedure EditIncreaseIndent(Sender: TObject);
+		procedure EditDecreaseIndent(Sender: TObject);
+		procedure FindDlgFind(Sender: TObject);
+		procedure ReplaceDlgReplace(Sender: TObject);
+		procedure FindString(Sender: TObject);
+		procedure FindFind(Sender: TObject);
+		procedure FindReplace(Sender: TObject);
+		procedure FindOpenFile(Sender: TObject);
+		procedure FunctionPopupPopup(Sender: TObject);
+		procedure FindFunctions(Sender: TObject);
+		procedure FindFunctionFromPopup(Sender: TObject);
+		procedure FileAddToProject(Sender: TObject);
+		procedure FormEnable(Sender: TObject);
+		procedure FormShow(Sender: TObject);
+    procedure FindDlgClose(Sender: TObject);
+	private
+		FSourceFile: TSourceFile;
+		procedure SetSourceFile(const Value: TSourceFile);
+		function GetEditor: TMemoComponent;
+	protected
+		procedure CreateParams(var Params: TCreateParams); override;
+	public
+		OriginalCaption: string;
+		EnableTimer: TTimer;
+		Funcs: TSourceFileFunctions;
+		procedure UpdateCaption;
+		procedure UpdateEditButtons;
+		procedure UpdateStatusBar;
+		procedure UpdateFuncs;
+		property SourceFile: TSourceFile read FSourceFile write SetSourceFile;
+		property Editor: TMemoComponent read GetEditor;
+{$IFDEF CODINGEXT}
+		procedure InitCodingExt;
+		procedure ActionFindSymbolExecute(Sender: TObject);
+{$ENDIF}
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	Printers,
+	UtilsDos, UtilsWin,
+	MasterUnit,
+	MainUnit, FunctionsWinUnit;
+
+procedure TSourceFileForm.SetSourceFile(const Value: TSourceFile);
+begin
+	FSourceFile := Value;
+	UpdateCaption;
+	if Assigned (SourceFile) and (SourceFile is TTextSourceFile) then
+		with SourceFile as TTextSourceFile do
+			if Assigned (TextEditor) then
+				with TextEditor do begin
+					OnKeyDown := MainForm.EditorKeyDown;
+					OnChange := EditorChange;
+					OnSelectionChange := EditorChange;
+					PopupMenu := EditorPopup;
+				end;
+	ActionFileCompile.Enabled := Assigned (SourceFile) and SourceFile.Compilable;
+	ActionFilePrint.Enabled := Assigned (SourceFile) and SourceFile.Printable and (Printer.Printers.Count > 0);
+	ActionFilePrintQuickly.Enabled := ActionFilePrint.Enabled;
+	ActionFindFunctions.Enabled := Assigned (SourceFile) and (SourceFile is TSourceTextSourceFile);
+	EditorChange (Editor);
+end;
+
+procedure TSourceFileForm.UpdateCaption;
+begin
+	if Assigned (SourceFile) then begin
+		Caption := OriginalCaption + ' - ' + SourceFile.SourceName;
+		if (MainForm.ProjectFile = '') and (ExtractFilePath (SourceFile.FileName) = 'C:\') then
+			StatusBar.Panels.Items[5].Text := ExtractFileName (SourceFile.FileName)
+		else
+			StatusBar.Panels.Items[5].Text := SourceFile.FileName;
+	end else
+		Caption := OriginalCaption;
+end;
+
+function TSourceFileForm.GetEditor: TMemoComponent;
+begin
+	if Assigned (SourceFile) and (SourceFile is TTextSourceFile) then
+		Result := (SourceFile as TTextSourceFile).TextEditor
+	else
+		Result := nil;
+end;
+
+procedure TSourceFileForm.FormClose(Sender: TObject;
+	var Action: TCloseAction);
+begin
+	if Assigned (SourceFile) and (SourceFile.ParentForm = Self) then begin
+		SourceFile.ParentForm := nil;
+		SourceFile.Free;
+	end;
+	Action := caFree;
+end;
+
+procedure TSourceFileForm.FormCloseQuery(Sender: TObject;
+	var CanClose: Boolean);
+begin
+	if Compiling then
+		CanClose := False
+	else if Assigned (SourceFile) and (SourceFile.ParentForm = Self) then
+		SourceFile.WarnIfModified;
+end;
+
+procedure TSourceFileForm.FormCreate(Sender: TObject);
+begin
+	OriginalCaption := Caption;
+{$IFDEF CODINGEXT}
+  InitCodingExt;
+{$ENDIF}
+end;
+
+procedure TSourceFileForm.ActionFileCloseExecute(Sender: TObject);
+begin
+	if not Compiling then
+		Close;
+end;
+
+procedure TSourceFileForm.FileSave(Sender: TObject);
+begin
+	if Assigned (SourceFile) then begin
+		SourceFile.Save;
+		UpdateCaption;
+	end;
+end;
+
+procedure TSourceFileForm.FileSaveAs(Sender: TObject);
+begin
+	if Assigned (SourceFile) then begin
+		SourceFile.SaveAs;
+		UpdateCaption;
+		UpdateStatusBar;
+	end;
+end;
+
+procedure TSourceFileForm.FileCompile(Sender: TObject);
+begin
+	if (not Compiling) and Assigned (SourceFile) then
+		with MainForm do begin
+			BeginCompilation;
+			CopyHeaders;
+			Self.SourceFile.Compile;
+			DeleteHeaders;
+			EndCompilation;
+		end;
+end;
+
+procedure TSourceFileForm.FilePrint(Sender: TObject);
+var
+	Cp: Integer;
+begin
+	if Assigned (SourceFile) and (Printer.Printers.Count > 0) then
+		with MainForm do try
+			PrintDlg.PrintRange := prAllPages;
+			PrintDlg.MaxPage := TSourceFile(ProjectTree.Selected.Data).CountPages;
+			PrintDlg.ToPage := PrintDlg.MaxPage;
+			if Assigned (CurrentEditor) then begin
+				if CurrentEditor.Selection.RLength > 0 then
+					PrintDlg.Options := PrintDlg.Options + [poSelection]
+				else
+					PrintDlg.Options := PrintDlg.Options - [poSelection];
+			end;
+			if Assigned (Sender) then begin
+				if not PrintDlg.Execute then
+					Abort;
+				Cp := PrintDlg.Copies;
+				if Cp < 1 then
+					Cp := 1;
+			end else
+				Cp := 1;
+			SourceFile.Print (Cp, PrintDlg.PrintRange, PrintDlg.FromPage, PrintDlg.ToPage);
+		except
+			Abort;
+		end;
+end;
+
+procedure TSourceFileForm.FilePrintQuickly(Sender: TObject);
+begin
+	FilePrint (nil);
+end;
+
+procedure TSourceFileForm.EditorChange(Sender: TObject);
+begin
+	UpdateEditButtons;
+	UpdateStatusBar;
+end;
+
+procedure TSourceFileForm.UpdateEditButtons;
+var
+	TextSel: Boolean;
+begin
+	if Assigned (Editor) then begin
+		TextSel := Editor.SelLength > 0;
+		ActionEditDelete.Enabled := TextSel;
+		ActionEditCut.Enabled := TextSel;
+		ActionEditCopy.Enabled := TextSel;
+		ActionEditUndo.Enabled := Editor.CanUndo;
+		ActionEditRedo.Enabled := Editor.CanRedo;
+	end;
+end;
+
+procedure TSourceFileForm.UpdateStatusBar;
+var
+	S: string;
+	I: Integer;
+	Cell: TTextCell;
+begin
+	with StatusBar.Panels do begin
+		if Assigned (Editor) then begin
+			with Editor do begin
+				if Enabled then begin
+					if Selection.RLength > 0 then begin
+						I := Selection.RLength + Selection.StartRowCol.Row - Selection.EndRowCol.Row;
+						if Selection.EndRowCol.Col > LineLength [Selection.EndRowCol.Row] then
+							Dec (I);
+						S := IntToStr (I);
+						if Items[0].Text <> S then
+							Items[0].Text := S;
+						if Items[1].Text <> '' then
+							Items[1].Text := '';
+						if Items[0].Width <> 60 then
+							Items[0].Width := 60;
+						if Items[1].Width <> 0 then
+							Items[1].Width := 0;
+					end else begin
+						Cell := Selection.StartRowCol;
+						S := IntToStr (Cell.Row);
+						if Items[0].Text <> S then
+							Items[0].Text := S;
+						S := IntToStr (Cell.Col);
+						if Items[1].Text <> S then
+							Items[1].Text := S;
+						if Items[0].Width <> 30 then
+							Items[0].Width := 30;
+						if Items[1].Width <> 30 then
+							Items[1].Width := 30;
+					end;
+					I := TextLength - LineCount + 1;
+					S := IntToStr (I) + ' Character';
+					if I <> 1 then
+						S := S + 's';
+					if Items[3].Text <> S then
+						Items[3].Text := S;
+					if Items[2].Width <> 1 then
+						Items[2].Width := 1;
+					if Items[3].Width <> 93 then
+						Items[3].Width := 93;
+					if Items[2].Width <> 1 then
+						Items[2].Width := 1;
+				end;
+			end;
+		end else begin
+			if Items[0].Text <> '' then
+				Items[0].Text := '';
+			if Items[1].Text <> '' then
+				Items[1].Text := '';
+			if Items[3].Text <> '' then
+				Items[3].Text := '';
+			if Items[0].Width <> 0 then
+				Items[0].Width := 0;
+			if Items[1].Width <> 0 then
+				Items[1].Width := 0;
+			if Items[2].Width <> 0 then
+				Items[2].Width := 0;
+			if Items[3].Width <> 0 then
+				Items[3].Width := 0;
+			if Items[4].Width <> 0 then
+				Items[4].Width := 0;
+		end;
+	end;
+	Update;
+end;
+
+procedure TSourceFileForm.EditUndo(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.Undo;
+end;
+
+procedure TSourceFileForm.EditRedo(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.Redo;
+end;
+
+procedure TSourceFileForm.EditDelete(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.ClearSelection;
+end;
+
+procedure TSourceFileForm.EditCut(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.CutToClipboard;
+end;
+
+procedure TSourceFileForm.EditCopy(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.CopyToClipboard;
+end;
+
+procedure TSourceFileForm.EditPaste(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.PasteFromClipboard;
+end;
+
+procedure TSourceFileForm.EditSelectAll(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.SelectAll;
+end;
+
+procedure TSourceFileForm.EditIncreaseIndent(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.ChangeIndent (1);
+end;
+
+procedure TSourceFileForm.EditDecreaseIndent(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		Editor.ChangeIndent (-1);
+end;
+
+procedure TSourceFileForm.FindDlgFind(Sender: TObject);
+begin
+	try
+		FindString (Sender);
+	except
+		ShowDefaultMessageBox ('Text ''' + (Sender as TFindDialog).FindText + ''' not found.', 'Search Failed', mtProgramError);
+	end;
+end;
+
+procedure TSourceFileForm.ReplaceDlgReplace(Sender: TObject);
+begin
+	if Assigned (Editor) then
+		with Sender as TReplaceDialog do
+			repeat
+				if UpperCase (Editor.Selection.Text) = UpperCase (FindText) then
+					Editor.Selection.Text := ReplaceText;
+				Options := Options + [frFindNext];
+				FindString (Sender);
+			until not (frReplaceAll in Options);
+end;
+
+procedure TSourceFileForm.FindString(Sender: TObject);
+var
+	P: Integer;
+	S,
+	T: string;
+	Valid: Boolean;
+	FPos: Integer;
+begin
+	if Assigned (Editor) then begin
+		with Sender as TFindDialog do begin
+			if frFindNext in Options then
+				P := Editor.SelStart + 1
+			else
+				if frDown in Options then
+					P := 1
+				else
+					P := Length (Editor.Text);
+			repeat
+				Valid := False;
+				if frDown in Options then
+					T := Copy (Editor.Text, P + 1, Length (Editor.Text))
+				else
+					T := Copy (Editor.Text, 1, P - 1);
+				if frMatchCase in Options then
+					S := FindText
+				else begin
+					S := UpperCase (FindText);
+					T := UpperCase (T);
+				end;
+				if frDown in Options then
+					FPos := Pos (S, T)
+				else
+					FPos := LastPos (S, T);
+				if FPos > 0 then begin
+					Valid := True;
+					if frWholeWord in Options then begin
+						if ((FPos > 1) and (T <> '') and (T [FPos - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'])) then
+							Valid := False;
+						if ((FPos + Length (S) < Length (T)) and (T <> '') and (T [FPos + Length (S)] in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'])) then
+							Valid := False;
+					end;
+					if not (frDown in Options) then
+						P := 0;
+					if not Valid then
+						Inc (P, FPos);
+				end;
+			until Valid or (FPos <= 0);
+			if Valid then begin
+				with Editor.Selection do begin
+					DoChanging;
+					RStart := P + FPos;
+					RLength := Length (S);
+					DoChange;
+					ScrollInView (2);
+				end;
+				SetFocus;
+			end else
+				Abort;
+		end;
+	end;
+end;
+
+procedure TSourceFileForm.FindFind(Sender: TObject);
+begin
+	FindDlg.Execute;
+	SetFocus;
+end;
+
+procedure TSourceFileForm.FindReplace(Sender: TObject);
+begin
+	ReplaceDlg.Execute;
+	SetFocus;
+end;
+
+procedure TSourceFileForm.FindOpenFile(Sender: TObject);
+var
+	I: Integer;
+	S: string;
+	QuotesInLine: Boolean;
+	SourceFile: TSourceFile;
+begin
+	if Assigned (Editor) then begin
+		QuotesInLine := Pos ('"', Editor.Lines [Editor.Selection.StartRowCol.Row - 1]) > 0;
+		S := '';
+		for I := Editor.Selection.RStart - 1 downto 1 do begin
+			if (not QuotesInLine) and (Editor.Text [I] = ' ') then
+				Break;
+			if Editor.Text [I] in [' ', 'A'..'Z', 'a'..'z', '0'..'9', '_', '-', '.', '\', ':'] then
+				S := Editor.Text [I] + S
+			else
+				Break;
+		end;
+		for I := Editor.Selection.RStart to Length (Editor.Text) do begin
+			if (not QuotesInLine) and (Editor.Text [I] = ' ') then
+				Break;
+			if Editor.Text [I] in [' ', 'A'..'Z', 'a'..'z', '0'..'9', '_', '-', '.', '\', ':'] then
+				S := S + Editor.Text [I]
+			else
+				Break;
+		end;
+		S := Trim (S);
+		if Length (S) > 0 then begin
+			SourceFile := MainForm.SourceFiles.FindFileNameOnly (S);
+			if Assigned (SourceFile) then
+				SourceFile.Edit
+			else begin
+				SourceFile := Self.SourceFile;
+				if FileExists (ExpandFileName (S)) then
+					MainForm.AddSourceFile (ExpandFileName (S), True)
+				else if Assigned (SourceFile) and (SourceFile is TGNUAsmSourceFile) and FileExists (WithBackslash (TIGCCFolder) + GASIncludeLocation + S) then
+					MainForm.AddSourceFile (WithBackslash (TIGCCFolder) + GASIncludeLocation + S, True)
+				else if Assigned (SourceFile) and (SourceFile is TAsmSourceFile) and FileExists (WithBackslash (TIGCCFolder) + ASMIncludeLocation + S) then
+					MainForm.AddSourceFile (WithBackslash (TIGCCFolder) + ASMIncludeLocation + S, True)
+				else if FileExists (WithBackslash (TIGCCFolder) + CIncludeLocation + S) then
+					MainForm.AddSourceFile (WithBackslash (TIGCCFolder) + CIncludeLocation + S, True)
+				else
+					ShowDefaultMessageBox ('File ''' + S + ''' not found.', 'Search Failed', mtProgramError);
+			end;
+		end;
+	end;
+end;
+
+procedure TSourceFileForm.FunctionPopupPopup(Sender: TObject);
+var
+	I: Integer;
+	M: TMenuItem;
+begin
+	with (Sender as TPopupMenu).Items do begin
+		for I := Count - 1 downto 0 do
+			Remove (Items [I]);
+		UpdateFuncs;
+		for I := Low (Funcs) to High (Funcs) do begin
+			M := TMenuItem.Create (Self);
+			with M do begin
+				Tag := I;
+				Caption := Funcs[I].Name;
+				OnClick := FindFunctionFromPopup;
+			end;
+			if (Pos ('main', Funcs[I].Name) > 0) and (Pos ('main', Funcs[I].Name) = Length (Funcs[I].Name) - Length ('main') + 1) then
+				Insert (0, M)
+			else
+				Add (M);
+		end;
+		if Count <= 0 then
+			Add (NoFunctionsItem);
+	end;
+end;
+
+procedure TSourceFileForm.FindFunctions(Sender: TObject);
+var
+	I: Integer;
+begin
+	UpdateFuncs;
+	with TFunctionsForm.Create (Self) do try
+		Funcs := @Self.Funcs;
+		with FuncList.Items do begin
+			BeginUpdate;
+			Clear;
+			for I := Low (Self.Funcs) to High (Self.Funcs) do
+				AddObject (Self.Funcs[I].Name, TObject (I));
+			EndUpdate;
+		end;
+		FuncListClick (FuncList);
+		case ShowModal of
+			mrYes: begin
+				if Assigned (Editor) then begin
+					Editor.Selection.NoSelAtPos (Editor.CellToCharIdx (TextCell (Self.Funcs[Integer(FuncList.Items.Objects[FuncList.ItemIndex])].PrototypeLine, 1)));
+					Editor.Selection.ScrollInView (5);
+				end;
+			end;
+			mrNo: begin
+				if Assigned (Editor) then begin
+					Editor.Selection.NoSelAtPos (Editor.CellToCharIdx (TextCell (Self.Funcs[Integer(FuncList.Items.Objects[FuncList.ItemIndex])].ImplementationLine, 1)));
+					Editor.Selection.ScrollInView (5);
+				end;
+			end;
+		end;
+		with FuncList.Items do begin
+			BeginUpdate;
+			for I := Count - 1 downto 0 do begin
+				Objects [I] := nil;
+				Delete (I);
+			end;
+			EndUpdate;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TSourceFileForm.UpdateFuncs;
+begin
+	if Assigned (SourceFile) and (SourceFile is TSourceTextSourceFile) then
+		with SourceFile as TSourceTextSourceFile do
+			Funcs := GetFunctions
+	else
+		SetLength (Funcs, 0);
+end;
+
+procedure TSourceFileForm.FindFunctionFromPopup(Sender: TObject);
+var
+	L: Integer;
+begin
+	if Sender is TMenuItem then
+		with Sender as TMenuItem do begin
+			if Funcs[Tag].ImplementationLine > 0 then
+				L := Funcs[Tag].ImplementationLine
+			else
+				L := Funcs[Tag].PrototypeLine;
+			if L > 0 then begin
+				if Assigned (Editor) then begin
+					Editor.Selection.NoSelAtPos (Editor.CellToCharIdx (TextCell (L, 1)));
+					Editor.Selection.ScrollInView (5);
+				end;
+			end;
+		end;
+end;
+
+procedure TSourceFileForm.FileAddToProject(Sender: TObject);
+var
+	N: TTreeNode;
+begin
+	if (not Compiling) and Assigned (SourceFile) then
+		with MainForm, SourceFile do begin
+			ParentForm := nil;
+			N := ProjectTree.Items.AddChildObject (TopNode.Item [ClassTreeIndex], SourceName, Pointer (SourceFile));
+			with N do begin
+				ImageIndex := ClassImageIndex;
+				SelectedIndex := ImageIndex;
+			end;
+			TreeItem := N;
+			if Assigned (Editor) then
+				with Editor do begin
+					Hide;
+					Parent := EditorPanel;
+					Align := alClient;
+				end;
+			if SourceFile is TTextSourceFile then
+				with SourceFile as TTextSourceFile do
+					if Assigned (TextEditor) then
+						with TextEditor do begin
+							OnEnter := EditorEnter;
+							OnExit := EditorExit;
+							OnKeyDown := EditorKeyDown;
+							OnChange := EditorChange;
+							OnSelectionChange := EditorChange;
+							PopupMenu := EditorPopup;
+						end;
+			SortFiles;
+			MainForm.Modify;
+			ProjectTree.Selected := N;
+			SourceFile := nil;
+			Self.Close;
+		end;
+end;
+
+procedure TSourceFileForm.FormEnable(Sender: TObject);
+begin
+	if Assigned (EnableTimer) then begin
+		EnableTimer.Free;
+		EnableTimer := nil;
+	end;
+	Enabled := True;
+	if Assigned (Editor) then begin
+		Editor.Enabled := False;
+		Editor.Enabled := True;
+		ActiveControl := Editor;
+	end;
+	SetFocus;
+end;
+
+procedure TSourceFileForm.FormShow(Sender: TObject);
+begin
+	if not (Enabled or Assigned (EnableTimer)) then begin
+		EnableTimer := TTimer.Create (Self);
+		EnableTimer.OnTimer := FormEnable;
+		EnableTimer.Interval := 100;
+		EnableTimer.Enabled := True;
+	end;
+end;
+
+procedure TSourceFileForm.CreateParams(var Params: TCreateParams);
+begin
+	inherited;
+	Params.WndParent := GetDesktopWindow;
+end;
+
+{$IFDEF CODINGEXT}
+procedure TSourceFileForm.InitCodingExt;
+var
+	ActionFindSymbol: TAction;
+begin
+	// Find Symbol declaration tool
+	ActionFindSymbol := TAction.Create(Self);
+	with ActionFindSymbol do begin
+		ActionList := Actions;
+		Caption := 'Find Symbol Declaration';
+		Category := 'Extension';
+		OnExecute := ActionFindSymbolExecute;
+	end;
+
+	InsertsAction(Self, [OpenFileAtCursor1, OpenFileatCursor2], ActionFindSymbol);
+end;
+
+procedure TSourceFileForm.ActionFindSymbolExecute(Sender: TObject);
+begin
+	CompForm.FindSymbolDecl;
+end;
+{$ENDIF}
+
+procedure TSourceFileForm.FindDlgClose(Sender: TObject);
+begin
+	SetFocus;
+end;
+
+end.
+

BIN
tigcc/ide/StartupScreenUnit.dfm


+ 58 - 0
tigcc/ide/StartupScreenUnit.pas

@@ -0,0 +1,58 @@
+unit StartupScreenUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ExtCtrls;
+
+type
+	TStartupScreenForm = class(TForm)
+		FramePanel: TPanel;
+		BackgroundPanel: TPanel;
+		BackgroundImage: TImage;
+		VersionLabel: TLabel;
+		NameLabel1: TLabel;
+		NameLabel3: TLabel;
+		NameLabel4: TLabel;
+		NameLabel5: TLabel;
+		NameLabel6: TLabel;
+		NameLabel7: TLabel;
+		NameLabel8: TLabel;
+    StartupStatusDisplay: TLabel;
+		procedure FormCreate(Sender: TObject);
+	private
+		function GetDisplayText: string;
+		procedure SetDisplayText(const Value: string);
+	public
+		property DisplayText: string read GetDisplayText write SetDisplayText;
+	end;
+
+var
+	StartupScreenForm: TStartupScreenForm;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	VersionUnit;
+
+procedure TStartupScreenForm.FormCreate(Sender: TObject);
+begin
+	PixelsPerInch := 96;
+	VersionLabel.Caption := TIGCCShortVersion;
+end;
+
+function TStartupScreenForm.GetDisplayText: string;
+begin
+	Result := StartupStatusDisplay.Caption;
+end;
+
+procedure TStartupScreenForm.SetDisplayText(const Value: string);
+begin
+	StartupStatusDisplay.Caption := Value;
+	Update;
+end;
+
+end.

BIN
tigcc/ide/StartupUnit.dfm


BIN
tigcc/ide/StyleSelectionUnit.dfm


+ 75 - 0
tigcc/ide/StyleSelectionUnit.pas

@@ -0,0 +1,75 @@
+unit StyleSelectionUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, ExtCtrls;
+
+type
+  TStyleSelectionForm = class(TForm)
+    CheckBox1: TCheckBox;
+    CheckBox2: TCheckBox;
+    CheckBox3: TCheckBox;
+    CheckBox4: TCheckBox;
+    CheckBox5: TCheckBox;
+    Bevel1: TBevel;
+    Button1: TButton;
+    Button2: TButton;
+    procedure CheckBox1Click(Sender: TObject);
+    procedure FormShow(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+  private
+	public
+		Style: TFontStyles;
+		CustomStyle: Boolean;
+	end;
+
+implementation
+
+{$R *.DFM}
+
+procedure TStyleSelectionForm.CheckBox1Click(Sender: TObject);
+begin
+	CheckBox2.Enabled := CheckBox1.Checked;
+	CheckBox3.Enabled := CheckBox1.Checked;
+	CheckBox4.Enabled := CheckBox1.Checked;
+	CheckBox5.Enabled := CheckBox1.Checked;
+	if not CheckBox2.Enabled then
+		CheckBox2.Checked := False;
+	if not CheckBox3.Enabled then
+		CheckBox3.Checked := False;
+	if not CheckBox4.Enabled then
+		CheckBox4.Checked := False;
+	if not CheckBox5.Enabled then
+		CheckBox5.Checked := False;
+end;
+
+procedure TStyleSelectionForm.FormShow(Sender: TObject);
+begin
+	CheckBox1.Checked := CustomStyle;
+	CheckBox2.Checked := fsBold in Style;
+	CheckBox3.Checked := fsItalic in Style;
+	CheckBox4.Checked := fsUnderline in Style;
+	CheckBox5.Checked := fsStrikeOut in Style;
+	CheckBox1Click (Sender);
+end;
+
+procedure TStyleSelectionForm.FormClose(Sender: TObject;
+	var Action: TCloseAction);
+begin
+	CustomStyle := CheckBox1.Checked;
+	if CustomStyle then begin
+		Style := [];
+		if CheckBox2.Checked then
+			Include (Style, fsBold);
+		if CheckBox3.Checked then
+			Include (Style, fsItalic);
+		if CheckBox4.Checked then
+			Include (Style, fsUnderline);
+		if CheckBox5.Checked then
+			Include (Style, fsStrikeOut);
+	end;
+end;
+
+end.

BIN
tigcc/ide/SyntaxProgressUnit.dfm


BIN
tigcc/ide/ToolPropertiesUnit.dfm


+ 82 - 0
tigcc/ide/ToolPropertiesUnit.pas

@@ -0,0 +1,82 @@
+unit ToolPropertiesUnit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, ExtCtrls;
+
+type
+  TToolPropertiesForm = class(TForm)
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    Label4: TLabel;
+    TitleEdit: TEdit;
+    CommandLineEdit: TEdit;
+    WorkingDirEdit: TEdit;
+    Bevel1: TBevel;
+    OKButton: TButton;
+    CancelButton: TButton;
+    WindowStateEdit: TComboBox;
+    CommandLineBrowseButton: TButton;
+    WorkingDirBrowseButton: TButton;
+    BrowseDialog: TOpenDialog;
+    procedure EditChange(Sender: TObject);
+    procedure CommandLineBrowseButtonClick(Sender: TObject);
+    procedure WorkingDirBrowseButtonClick(Sender: TObject);
+  private
+	public
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	ShlObj;
+
+procedure TToolPropertiesForm.EditChange(Sender: TObject);
+begin
+	OKButton.Enabled := (Length (TitleEdit.Text) > 0) and (Length (CommandLineEdit.Text) > 0);
+end;
+
+procedure TToolPropertiesForm.CommandLineBrowseButtonClick(Sender: TObject);
+var
+	S: string;
+begin
+	with BrowseDialog do begin
+		S := CommandLineEdit.Text;
+		if (Length (S) > 0) and ((S [1] = '"') or (Pos (' ', S) <= 0)) then begin
+			if S [1] = '"' then begin
+				Delete (S, 1, 1);
+				if Pos ('"', S) > 0 then
+					Delete (S, Pos ('"', S), Length (S));
+			end;
+			FileName := S;
+		end;
+		if Execute then
+			CommandLineEdit.Text := '"' + FileName + '"';
+	end;
+end;
+
+procedure TToolPropertiesForm.WorkingDirBrowseButtonClick(Sender: TObject);
+var
+	Info: TBrowseInfo;
+	Path: PItemIDList;
+	FolderName: array [0..MAX_PATH] of Char;
+begin
+	FillChar (Info, SizeOf (Info), 0);
+	with Info do begin
+		hwndOwner := Handle;
+		lpszTitle := 'Browse';
+		ulFlags := BIF_RETURNONLYFSDIRS;
+	end;
+	Path := SHBrowseForFolder (Info);
+	if Assigned (Path) then begin
+		if SHGetPathFromIDList (Path, FolderName) then
+			WorkingDirEdit.Text := FolderName;
+	end;
+end;
+
+end.

+ 40 - 0
tigcc/ide/ToolsListUnit.pas

@@ -0,0 +1,40 @@
+unit ToolsListUnit;
+
+interface
+
+uses
+	ObjList,
+	Classes, Controls, Forms, Menus;
+
+type
+	TToolsList = class(TFastObjectContainer);
+
+	TToolsListItem = class(TFastContainerItem)
+	private
+		FWorkingDir: string;
+		FCommandLine: string;
+		FTitle: TCaption;
+		FWindowState: TWindowState;
+    FMenuItem: TMenuItem;
+	public
+		destructor Destroy; override;
+		property MenuItem: TMenuItem read FMenuItem write FMenuItem;
+	published
+		property Title: TCaption read FTitle write FTitle;
+		property CommandLine: string read FCommandLine write FCommandLine;
+		property WorkingDir: string read FWorkingDir write FWorkingDir;
+		property WindowState: TWindowState read FWindowState write FWindowState;
+	end;
+
+implementation
+
+{ TToolsListItem }
+
+destructor TToolsListItem.Destroy;
+begin
+	if Assigned (MenuItem) then
+		MenuItem.Free;
+	inherited;
+end;
+
+end.

BIN
tigcc/ide/ToolsUnit.dfm


+ 179 - 0
tigcc/ide/ToolsUnit.pas

@@ -0,0 +1,179 @@
+unit ToolsUnit;
+
+interface
+
+uses
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ComCtrls;
+
+type
+	TToolsForm = class(TForm)
+		ToolsList: TListView;
+		AddButton: TButton;
+		EditButton: TButton;
+		RemoveButton: TButton;
+		OKButton: TButton;
+		CancelButton: TButton;
+		procedure AddButtonClick(Sender: TObject);
+		procedure EditButtonClick(Sender: TObject);
+		procedure RemoveButtonClick(Sender: TObject);
+		procedure ToolsListSelectItem(Sender: TObject; Item: TListItem;
+			Selected: Boolean);
+		procedure ToolsListKeyDown(Sender: TObject; var Key: Word;
+			Shift: TShiftState);
+		procedure ToolsListDragDrop(Sender, Source: TObject; X, Y: Integer);
+		procedure ToolsListDragOver(Sender, Source: TObject; X, Y: Integer;
+			State: TDragState; var Accept: Boolean);
+	private
+	public
+		function WindowStateToString(WindowState: TWindowState): string;
+		function StringToWindowState(const S: string): TWindowState;
+	end;
+
+const
+	NormalString = 'Normal';
+	MaximizedString = 'Maximized';
+	MinimizedString = 'Minimized';
+
+implementation
+
+{$R *.DFM}
+
+uses
+	ToolPropertiesUnit;
+
+procedure TToolsForm.AddButtonClick(Sender: TObject);
+begin
+	with TToolPropertiesForm.Create (Self) do try
+		WindowStateEdit.ItemIndex := 0;
+		if ShowModal = mrOK then begin
+			with ToolsList.Items.Add do begin
+				Caption := TitleEdit.Text;
+				SubItems.Add (CommandLineEdit.Text);
+				SubItems.Add (WorkingDirEdit.Text);
+				SubItems.Add (WindowStateEdit.Text);
+			end;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TToolsForm.EditButtonClick(Sender: TObject);
+begin
+	if Assigned (ToolsList.Selected) then
+		with TToolPropertiesForm.Create (Self) do try
+			with ToolsList.Selected do begin
+				TitleEdit.Text := Caption;
+				CommandLineEdit.Text := SubItems [0];
+				WorkingDirEdit.Text := SubItems [1];
+				case StringToWindowState (SubItems [2]) of
+					wsMaximized:
+						WindowStateEdit.ItemIndex := 1;
+					wsMinimized:
+						WindowStateEdit.ItemIndex := 2;
+					else
+						WindowStateEdit.ItemIndex := 0;
+				end;
+			end;
+			if ShowModal = mrOK then begin
+				with ToolsList.Selected do begin
+					Caption := TitleEdit.Text;
+					SubItems [0] := CommandLineEdit.Text;
+					SubItems [1] := WorkingDirEdit.Text;
+					case WindowStateEdit.ItemIndex of
+						1:
+							SubItems [2] := MaximizedString;
+						2:
+							SubItems [2] := MinimizedString;
+						else
+							SubItems [2] := NormalString;
+					end;
+				end;
+			end;
+		finally
+			Free;
+		end;
+end;
+
+procedure TToolsForm.RemoveButtonClick(Sender: TObject);
+begin
+	if Assigned (ToolsList.Selected) then
+		ToolsList.Selected.Free;
+end;
+
+procedure TToolsForm.ToolsListSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
+begin
+	EditButton.Enabled := Assigned (ToolsList.Selected);
+	RemoveButton.Enabled := Assigned (ToolsList.Selected);
+end;
+
+procedure TToolsForm.ToolsListKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+	if Key = vk_Delete then
+		RemoveButtonClick (Sender);
+end;
+
+procedure TToolsForm.ToolsListDragDrop(Sender, Source: TObject; X, Y: Integer);
+var
+	S,
+	D: TListItem;
+	DIndex: Integer;
+begin
+	with ToolsList do begin
+		S := Selected;
+		if Assigned (S) then begin
+			D := GetItemAt (X, Y);
+			if Assigned (D) and (S <> D) then begin
+				DIndex := D.Index;
+				if DIndex > S.Index then
+					Inc (DIndex);
+				with Items.Insert (DIndex) do begin
+					Caption := S.Caption;
+					SubItems.Assign (S.SubItems);
+				end;
+				S.Free;
+			end;
+		end;
+	end;
+end;
+
+procedure TToolsForm.ToolsListDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
+var
+	S,
+	D: TListItem;
+begin
+	Accept := False;
+	with ToolsList do begin
+		S := Selected;
+		if Assigned (S) then begin
+			D := GetItemAt (X, Y);
+			if Assigned (D) and (S <> D) then
+				Accept := True;
+		end;
+	end;
+end;
+
+function TToolsForm.WindowStateToString(WindowState: TWindowState): string;
+begin
+	case WindowState of
+		wsMaximized:
+			Result := MaximizedString;
+		wsMinimized:
+			Result := MinimizedString;
+		else
+			Result := NormalString;
+	end;
+end;
+
+function TToolsForm.StringToWindowState(const S: string): TWindowState;
+begin
+	if S = MaximizedString then
+		Result := wsMaximized
+	else if S = MinimizedString then
+		Result := wsMinimized
+	else
+		Result := wsNormal;
+end;
+
+end.

BIN
tigcc/ide/VTIStartUnit.dfm


+ 76 - 0
tigcc/ide/VTIStartUnit.pas

@@ -0,0 +1,76 @@
+unit VTIStartUnit;
+
+interface
+
+uses
+	MasterUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+	StdCtrls, ExtCtrls;
+
+type
+	TVTIStartForm = class(TForm)
+		Label1: TLabel;
+		CancelButton: TButton;
+    FindTimer: TTimer;
+		procedure FormShow(Sender: TObject);
+		procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure FindTimerTimer(Sender: TObject);
+	private
+		ProcessHandle: THandle;
+	public
+		VTIWindow: HWnd;
+		VTIType: TCurVTIType;
+	end;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	UtilsWin;
+
+procedure TVTIStartForm.FormShow(Sender: TObject);
+var
+	StartupInfo: TStartupInfo;
+	ProcessInfo: TProcessInformation;
+begin
+	FillChar (StartupInfo, SizeOf (StartupInfo), 0);
+	StartupInfo.cb := SizeOf (StartupInfo);
+	if CreateProcess (nil, PChar (VTIPath), nil, nil, False, CREATE_NEW_PROCESS_GROUP or DETACHED_PROCESS, nil, PChar (ExtractFilePath (VTIPath)), StartupInfo, ProcessInfo) then begin
+		ProcessHandle := ProcessInfo.hProcess;
+		CloseHandle (ProcessInfo.hThread);
+	end else begin
+		ShowDefaultMessageBox ('An error occurred while trying to start Virtual TI.', 'Error', mtProgramError);
+		ModalResult := mrAbort;
+	end;
+end;
+
+procedure TVTIStartForm.FormClose(Sender: TObject;
+	var Action: TCloseAction);
+begin
+	if ProcessHandle <> 0 then
+		CloseHandle (ProcessHandle);
+end;
+
+procedure TVTIStartForm.FindTimerTimer(Sender: TObject);
+var
+	ExitCode: Cardinal;
+begin
+	if GetExitCodeProcess (ProcessHandle, ExitCode) then begin
+		if ExitCode <> STILL_ACTIVE then begin
+			ModalResult := mrAbort;
+			Exit;
+		end;
+	end;
+	VTIWindow := FindWindow ('TEmuWnd', 'Virtual TI-89');
+	if VTIWindow = 0 then begin
+		VTIWindow := FindWindow ('TEmuWnd', 'Virtual TI-92+');
+		if VTIWindow <> 0 then
+			VTIType := cvTI92Plus;
+	end else
+		VTIType := cvTI89;
+	if VTIWindow <> 0 then
+		ModalResult := mrOK;
+end;
+
+end.

+ 12 - 0
tigcc/ide/VersionUnit.pas

@@ -0,0 +1,12 @@
+unit VersionUnit;
+{ This file is generated automatically. }
+
+interface
+
+const
+	TIGCCShortVersion = '0.95';
+	TIGCCLongVersion = '0.95';
+
+implementation
+
+end.

BIN
tigcc/ide/WordListUnit.dfm


+ 93 - 0
tigcc/ide/WordListUnit.pas

@@ -0,0 +1,93 @@
+unit WordListUnit;
+
+interface
+
+uses
+	SourceEditUnit,
+	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, ExtCtrls;
+
+type
+	TWordListForm = class(TForm)
+    Button1: TButton;
+    Button2: TButton;
+    ColorDlg: TColorDialog;
+    Bevel1: TBevel;
+    Bevel2: TBevel;
+    Button3: TButton;
+    Button4: TButton;
+    ListStrings: TMemo;
+    CaseSensitiveBox: TCheckBox;
+		procedure FormCreate(Sender: TObject);
+		procedure FormDestroy(Sender: TObject);
+    procedure Button1Click(Sender: TObject);
+    procedure Button2Click(Sender: TObject);
+    procedure FormShow(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure CaseSensitiveBoxClick(Sender: TObject);
+	private
+	public
+		List: TWordList;
+	end;
+
+var
+	WordListForm: TWordListForm;
+
+implementation
+
+{$R *.DFM}
+
+uses
+	StyleSelectionUnit;
+
+procedure TWordListForm.FormCreate(Sender: TObject);
+begin
+	List := TWordList.Create (nil);
+end;
+
+procedure TWordListForm.FormDestroy(Sender: TObject);
+begin
+	List.Free;
+end;
+
+procedure TWordListForm.Button1Click(Sender: TObject);
+begin
+	ColorDlg.Color := List.Color;
+	if ColorDlg.Execute then begin
+		List.Color := ColorDlg.Color;
+		List.CustomColor := True;
+	end;
+end;
+
+procedure TWordListForm.Button2Click(Sender: TObject);
+begin
+	with TStyleSelectionForm.Create (Self) do try
+		CustomStyle := List.CustomStyle;
+		Style := List.Style;
+		if ShowModal = mrOK then begin
+			List.CustomStyle := CustomStyle;
+			List.Style := Style;
+		end;
+	finally
+		Free;
+	end;
+end;
+
+procedure TWordListForm.FormShow(Sender: TObject);
+begin
+	ListStrings.Lines.Assign (List.Words);
+	CaseSensitiveBox.Checked := List.CaseSensitive;
+end;
+
+procedure TWordListForm.FormClose(Sender: TObject;
+	var Action: TCloseAction);
+begin
+	List.Words.Assign (ListStrings.Lines);
+end;
+
+procedure TWordListForm.CaseSensitiveBoxClick(Sender: TObject);
+begin
+	List.CaseSensitive := CaseSensitiveBox.Checked;
+end;
+
+end.

+ 340 - 0
tigcc/ld-tigcc/GPL.txt

@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

+ 71 - 0
tigcc/ld-tigcc/Makefile

@@ -0,0 +1,71 @@
+ifeq ($(OSTYPE), msys)
+EXEEXT = .exe
+else
+EXEEXT =
+endif
+
+LD_TIGCC = ld-tigcc$(EXEEXT)
+AR_TIGCC = ar-tigcc$(EXEEXT)
+LINK_DLL = link.dll
+
+ifeq ($(OSTYPE),msys)
+ALL_TARGETS = $(LD_TIGCC) $(AR_TIGCC) $(LINK_DLL)
+else
+ALL_TARGETS = $(LD_TIGCC) $(AR_TIGCC)
+endif
+
+CC = gcc
+CFLAGS = -s -Os -fno-exceptions
+WARN_CFLAGS = -W -Wall -Wwrite-strings -Wpointer-arith
+DEFINES = -DCOFF_SUPPORT -DAMIGAOS_SUPPORT -DTIOS_SUPPORT -DFLASH_OS_SUPPORT -DNOSTUB_DLL_SUPPORT -DFARGO_SUPPORT -DDATA_VAR_SUPPORT -DTIOS_FILE_SUPPORT -DTIOS_UPGRADE_FILE_SUPPORT -DCOFF_TIGCC_EXTENSIONS -DAMIGAOS_TIGCC_EXTENSIONS
+EXE_DEFINES = -DENABLE_HELP -DENABLE_STATS -DENABLE_DUMP
+
+RM = rm
+RMFLAGS = -f
+
+COMPILE_C = $(CC) -c $(CFLAGS) $(ARCHFLAGS) $(WARN_CFLAGS) $(DEFINES)
+
+HEADERS = *.h formats/*.h import/*.h export/*.h bincode/*.h insert/*.h insert/model/*.h int_def.inc
+AR_HEADERS = ar/*.h ar/import/*.h ar/export/*.h *.h formats/*.h
+OBJECTS = main.o integers.o int_arb.o manip.o constmrg.o reorder.o import/import.o import/imp_coff.o import/imp_amig.o import/imp_ar.o export/export.o export/exp_def.o export/exp_os.o export/exp_tios.o export/exp_ndll.o export/exp_farg.o export/exp_data.o bincode/fix_m68k.o bincode/fix_tios.o bincode/fix_emu.o bincode/cutrange.o insert/ins_def.o insert/model/list.o insert/kernel.o insert/comprrlc.o insert/other.o special.o dump.o
+AR_OBJECTS = ar/main.o ar/manip.o ar/import/import.o ar/import/imp_coff.o ar/import/imp_amig.o ar/export/exp_ar.o ar/dump.o integers.o
+DLL_OBJECTS = main.do integers.do int_arb.do manip.do constmrg.do reorder.do import/import.do import/imp_coff.do import/imp_amig.do import/imp_ar.do export/export.do export/exp_def.do export/exp_os.do export/exp_tios.do export/exp_ndll.do export/exp_farg.do export/exp_data.do bincode/fix_m68k.do bincode/fix_tios.do bincode/fix_emu.do bincode/cutrange.do insert/ins_def.do insert/model/list.do insert/kernel.do insert/comprrlc.do insert/other.do special.do
+DLL_AR_OBJECTS = ar/main.do ar/manip.do ar/import/import.do ar/import/imp_coff.do ar/import/imp_amig.do ar/export/exp_ar.do
+BACKUPS = *~ format/*~ import/*~ export/*~ bincode/*~ insert/*~ insert/model/*~ ar/*~ ar/import/*~ ar/export/*~
+
+.PHONY: all clean clean_backups
+
+all: $(ALL_TARGETS)
+
+ar/main.o: ar/main.c ar/main_opt.inc $(AR_HEADERS)
+	$(COMPILE_C) $(EXE_DEFINES) $< -o $@
+
+ar/%.o: ar/%.c $(AR_HEADERS)
+	$(COMPILE_C) $(EXE_DEFINES) $< -o $@
+
+ar/%.do: ar/%.c $(AR_HEADERS)
+	$(COMPILE_C) -DTARGET_DLL $< -o $@
+
+main.o: main.c main_opt.inc main_vbs.inc $(HEADERS)
+	$(COMPILE_C) $(EXE_DEFINES) $< -o $@
+
+%.o: %.c $(HEADERS)
+	$(COMPILE_C) $(EXE_DEFINES) $< -o $@
+
+%.do: %.c $(HEADERS)
+	$(COMPILE_C) -DTARGET_DLL $< -o $@
+
+$(LD_TIGCC): $(OBJECTS)
+	$(CC) $(CFLAGS) $(ARCHFLAGS) $(OBJECTS) -o $@
+
+$(AR_TIGCC): $(AR_OBJECTS)
+	$(CC) $(CFLAGS) $(ARCHFLAGS) $(AR_OBJECTS) -o $@
+
+$(LINK_DLL): $(DLL_OBJECTS) $(DLL_AR_OBJECTS)
+	$(CC) -shared --dll $(CFLAGS) $(ARCHFLAGS) $(DLL_OBJECTS) $(DLL_AR_OBJECTS) -o $@
+
+clean:
+	-$(RM) $(RMFLAGS) $(OBJECTS) $(AR_OBJECTS) $(DLL_OBJECTS) $(DLL_AR_OBJECTS) $(ALL_TARGETS)
+
+clean_backups:
+	-$(RM) $(RMFLAGS) $(BACKUPS)

+ 5 - 0
tigcc/ld-tigcc/ToDo.txt

@@ -0,0 +1,5 @@
+ TO DO LIST FOR LD-TIGCC
+=========================
+
+* Add debug information dump.
+* Implement absolute symbols.

+ 82 - 0
tigcc/ld-tigcc/ar/data.h

@@ -0,0 +1,82 @@
+/* data.h: Definitions for internal data handling
+
+   Copyright (C) 2003 Sebastian Reichelt
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DATA_H
+#define DATA_H
+
+#include "../generic.h"
+#include "../lists.h"
+#include "../filestat.h"
+
+#define MAX_SYM_LEN 255
+
+struct ARCHIVE;
+struct OBJECT_FILE;
+struct SYMBOL;
+
+struct SYMBOL_TABLE;
+
+// Complete Archive
+typedef struct ARCHIVE {
+	struct {
+		LIST_HEADER(struct OBJECT_FILE);
+	} ObjectFiles;        // Object files contained in the archive.
+	FILE_STATS FileStats; // Statistics of the file.
+	COUNT SymbolCount;    // Number of symbols in the archive.
+	// Export help
+	SIZE ArFileSize;      // Size of the entire archive.
+	struct SYMBOL_TABLE *SymbolTable; // Symbol table information.
+} ARCHIVE;
+
+// Object File
+typedef struct OBJECT_FILE {
+	LIST_ITEM_HEADER(struct OBJECT_FILE);
+	ARCHIVE *Parent;
+	I1 *Data;             // Pointer to file contents (needs to be freed at the end).
+	SIZE Size;            // Size of file.
+	struct {
+		LIST_HEADER(struct SYMBOL);
+	} Symbols;            // Exported symbols.
+	const char *FileName; // File name.
+	FILE_STATS FileStats; // Statistics of the file.
+	// Export help
+	SIZE ArMemberSize;    // Size of the archive member, including padding.
+	OFFSET ArMemberOffset; // Offset of the member inside the archive file.
+} OBJECT_FILE;
+
+// Exported Symbol in an Object File
+typedef struct SYMBOL {
+	LIST_ITEM_HEADER(struct SYMBOL);
+	OBJECT_FILE *Parent;
+	char Name[MAX_SYM_LEN+1]; // Symbol name.
+	SIZE NameLength;      // Length of the symbol name.
+} SYMBOL;
+
+// Archive Symbol Table in Internal Representation
+typedef struct SYMBOL_TABLE {
+	ARCHIVE *Parent;
+	SIZE Size;            // Size of the symbol table when it is written to the archive.
+	// Export help
+	SIZE ArMemberSize;    // Size of the archive member, including padding.
+	OFFSET ArMemberOffset; // Offset of the member inside the archive file.
+	// Symbol array
+	COUNT SymbolCount;    // Number of symbols.
+	SYMBOL *Symbols VAR_ARRAY; // An array pointing to the symbols in this table.
+} SYMBOL_TABLE;
+
+#endif

+ 61 - 0
tigcc/ld-tigcc/ar/dump.c

@@ -0,0 +1,61 @@
+/* dump.c: Routines to dump the internal data to a file
+
+   Copyright (C) 2003 Sebastian Reichelt
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "dump.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define FixIndent \
+	SIZE NewLen = (Indent ? strlen (Indent) : 0) + 2; \
+	char NextIndent[NewLen+1]; \
+	if (!Indent) \
+		Indent = ""; \
+	strcpy (NextIndent, Indent); \
+	NextIndent [NewLen - 2] = ' '; \
+	NextIndent [NewLen - 1] = ' '; \
+	NextIndent [NewLen] = 0;
+
+void DumpArchive (FILE *File, const char *Indent, const ARCHIVE *Archive)
+{
+	OBJECT_FILE *ObjectFile;
+	
+	FixIndent;
+	
+	for_each (ObjectFile, Archive->ObjectFiles)
+	{
+		if (ObjectFile->FileName)
+			fprintf (File, "%s%s\n", Indent, ObjectFile->FileName);
+		else
+			fprintf (File, "%s(unnamed)\n", Indent);
+		
+		DumpObjectFile (File, NextIndent, ObjectFile);
+	}
+}
+
+void DumpObjectFile (FILE *File, const char *Indent, const OBJECT_FILE *ObjectFile)
+{
+	SYMBOL *Symbol;
+	
+	FixIndent;
+	
+	for_each (Symbol, ObjectFile->Symbols)
+	{
+		fprintf (File, "%s%s\n", Indent, Symbol->Name);
+	}
+}

+ 33 - 0
tigcc/ld-tigcc/ar/dump.h

@@ -0,0 +1,33 @@
+/* dump.h: Routines to dump the internal data to a file
+
+   Copyright (C) 2003 Sebastian Reichelt
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DUMP_H
+#define DUMP_H
+
+#include "../generic.h"
+#include "data.h"
+
+#include <stdio.h>
+
+// Dump everything.
+void DumpArchive (FILE *File, const char *Indent, const ARCHIVE *Archive);
+
+// Dump a single object file.
+void DumpObjectFile (FILE *File, const char *Indent, const OBJECT_FILE *ObjectFile);
+
+#endif

Деякі файли не було показано, через те що забагато файлів було змінено