Major Java code cleanup:
1. Renamed packages org.eclipse to com.google.eclipse
2. Reformatted the code
3. Removed API analysis
4. Removed NLS-related warnings
5. Updated code to use new features in Java 1.5
6. Removed compiler warnings
7. Removed unnecessary code
8. Removed code duplication
diff --git a/com.google.eclipse.cdt.core.linux.x86/build.properties b/com.google.eclipse.cdt.core.linux.x86/build.properties
index 9faf19a..e16c8a6 100644
--- a/com.google.eclipse.cdt.core.linux.x86/build.properties
+++ b/com.google.eclipse.cdt.core.linux.x86/build.properties
@@ -9,6 +9,4 @@
# IBM Corporation - initial API and implementation
###############################################################################
bin.includes = os/,\
- about.html,\
META-INF/
-src.includes = about.html
diff --git a/com.google.eclipse.cdt.core/.project b/com.google.eclipse.cdt.core/.project
index 2553bca..fa9ad7d 100644
--- a/com.google.eclipse.cdt.core/.project
+++ b/com.google.eclipse.cdt.core/.project
@@ -20,15 +20,9 @@
<arguments>
</arguments>
</buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
</natures>
</projectDescription>
diff --git a/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.core.prefs
index 07dc692..c537b63 100644
--- a/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.core.prefs
@@ -1,342 +1,7 @@
-#Mon Oct 17 17:36:13 PDT 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=error
-org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
-org.eclipse.jdt.core.compiler.problem.nullReference=error
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.6
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=true
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=true
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
-org.eclipse.jdt.core.formatter.comment.format_line_comments=true
-org.eclipse.jdt.core.formatter.comment.format_source_code=true
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.jdt.core.formatter.comment.line_length=110
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=2
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
-org.eclipse.jdt.core.formatter.indentation.size=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.join_lines_in_comments=true
-org.eclipse.jdt.core.formatter.join_wrapped_lines=true
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=100
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=tab
-org.eclipse.jdt.core.formatter.tabulation.size=4
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.ui.prefs b/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index b6ac6d0..0000000
--- a/com.google.eclipse.cdt.core/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,5 +0,0 @@
-#Wed Jan 28 12:19:26 CET 2009
-eclipse.preferences.version=1
-formatter_profile=_CDT
-formatter_settings_version=11
-internal.default.compliance=user
diff --git a/com.google.eclipse.cdt.core/.settings/org.eclipse.pde.api.tools.prefs b/com.google.eclipse.cdt.core/.settings/org.eclipse.pde.api.tools.prefs
deleted file mode 100644
index b8a147b..0000000
--- a/com.google.eclipse.cdt.core/.settings/org.eclipse.pde.api.tools.prefs
+++ /dev/null
@@ -1,178 +0,0 @@
-ANNOTATION_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_METHOD=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_TYPE_MEMBER=Error
-ANNOTATION_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_INTERFACE_BOUNDS=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_TO_CLASS=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_TO_ENUM=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_TO_INTERFACE=Error
-ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD_WITHOUT_DEFAULT_VALUE=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD_WITH_DEFAULT_VALUE=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
-ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error
-API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
-API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
-API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
-API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
-API_USE_SCAN_FIELD_SEVERITY=Error
-API_USE_SCAN_METHOD_SEVERITY=Error
-API_USE_SCAN_TYPE_SEVERITY=Error
-CLASS_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
-CLASS_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
-CLASS_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error
-CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
-CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
-CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
-CLASS_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
-CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERCLASS_SET=Error
-CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
-CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
-CLASS_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
-CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
-CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
-CLASS_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
-CLASS_ELEMENT_TYPE_CHANGED_SUPERCLASS=Error
-CLASS_ELEMENT_TYPE_CHANGED_TO_ANNOTATION=Error
-CLASS_ELEMENT_TYPE_CHANGED_TO_ENUM=Error
-CLASS_ELEMENT_TYPE_CHANGED_TO_INTERFACE=Error
-CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
-CLASS_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
-CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
-CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
-CLASS_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
-CLASS_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error
-CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
-CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
-CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
-CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
-CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error
-CONSTRUCTOR_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
-CONSTRUCTOR_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
-CONSTRUCTOR_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error
-CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_TYPE_PARAMETER=Error
-CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
-CONSTRUCTOR_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
-CONSTRUCTOR_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
-CONSTRUCTOR_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
-CONSTRUCTOR_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error
-CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
-CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error
-ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
-ENUM_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
-ENUM_ELEMENT_TYPE_CHANGED_TO_ANNOTATION=Error
-ENUM_ELEMENT_TYPE_CHANGED_TO_CLASS=Error
-ENUM_ELEMENT_TYPE_CHANGED_TO_INTERFACE=Error
-ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
-ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
-ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
-ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
-ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
-FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
-FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
-FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
-FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
-FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
-FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
-FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
-FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
-FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
-FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENTS=Error
-FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
-ILLEGAL_EXTEND=Warning
-ILLEGAL_IMPLEMENT=Warning
-ILLEGAL_INSTANTIATE=Warning
-ILLEGAL_OVERRIDE=Warning
-ILLEGAL_REFERENCE=Warning
-INTERFACE_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
-INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
-INTERFACE_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
-INTERFACE_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error
-INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
-INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
-INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
-INTERFACE_ELEMENT_TYPE_ADDED_TYPE_MEMBER=Error
-INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
-INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETERS=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_INTERFACE_BOUNDS=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_TO_ANNOTATION=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_TO_CLASS=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_TO_ENUM=Error
-INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
-INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
-INVALID_JAVADOC_TAG=Error
-INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Warning
-LEAK_EXTEND=Warning
-LEAK_FIELD_DECL=Warning
-LEAK_IMPLEMENT=Warning
-LEAK_METHOD_PARAM=Warning
-LEAK_METHOD_RETURN_TYPE=Warning
-METHOD_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
-METHOD_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
-METHOD_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error
-METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
-METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
-METHOD_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
-METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
-METHOD_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
-METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
-METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
-METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
-METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
-METHOD_ELEMENT_TYPE_CHANGED_TYPE_PARAMETER=Error
-METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
-METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
-METHOD_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
-METHOD_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
-METHOD_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error
-METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
-METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error
-MISSING_EE_DESCRIPTIONS=Ignore
-TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
-TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
-TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
-TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
-TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
-TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
-UNUSED_PROBLEM_FILTERS=Warning
-automatically_removed_unused_problem_filters=false
-eclipse.preferences.version=1
-incompatible_api_component_version=Error
-incompatible_api_component_version_include_major_without_breaking_change=Disabled
-incompatible_api_component_version_include_minor_without_api_change=Disabled
-invalid_since_tag_version=Error
-malformed_since_tag=Error
-missing_since_tag=Error
-report_api_breakage_when_major_version_incremented=Disabled
-report_resolution_errors_api_component=Warning
diff --git a/com.google.eclipse.cdt.core/META-INF/MANIFEST.MF b/com.google.eclipse.cdt.core/META-INF/MANIFEST.MF
index a1688a2..cbe79bd 100644
--- a/com.google.eclipse.cdt.core/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.cdt.core/META-INF/MANIFEST.MF
@@ -2,13 +2,13 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: com.google.eclipse.cdt.core;singleton:=true
-Bundle-Version: 5.4.0.qualifier
-Bundle-Activator: org.eclipse.cdt.core.CCorePlugin
+Bundle-Version: 1.1.0.qualifier
+Bundle-Activator: com.google.eclipse.cdt.core.CCorePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
-Export-Package: org.eclipse.cdt.core,
- org.eclipse.cdt.internal.core,
- org.eclipse.cdt.utils,
+Export-Package: com.google.eclipse.cdt.core,
+ com.google.eclipse.cdt.internal.core,
+ com.google.eclipse.cdt.utils,
org.eclipse.cdt.utils.pty,
org.eclipse.cdt.utils.spawner
Require-Bundle: org.eclipse.core.resources,
diff --git a/com.google.eclipse.cdt.core/src/com/google/eclipse/cdt/core/CCorePlugin.java b/com.google.eclipse.cdt.core/src/com/google/eclipse/cdt/core/CCorePlugin.java
new file mode 100644
index 0000000..a034126
--- /dev/null
+++ b/com.google.eclipse.cdt.core/src/com/google/eclipse/cdt/core/CCorePlugin.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.cdt.core;
+
+import java.util.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ * Life-cycle owner of the core plug-in, and starting point for access to many core APIs.
+ */
+public class CCorePlugin extends Plugin {
+ public static final String PLUGIN_ID = "org.eclipse.cdt.core";
+
+ private static CCorePlugin plugin;
+ private static ResourceBundle resourceBundle;
+
+ static {
+ try {
+ resourceBundle = ResourceBundle.getBundle("com.google.eclipse.cdt.internal.core.CCorePluginResources");
+ } catch (MissingResourceException x) {
+ resourceBundle = null;
+ }
+ }
+
+ public CCorePlugin() {
+ plugin = this;
+ }
+
+ public static String getResourceString(String key) {
+ try {
+ return resourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";
+ } catch (NullPointerException e) {
+ return "#" + key + "#";
+ }
+ }
+
+ public static IWorkspace getWorkspace() {
+ return ResourcesPlugin.getWorkspace();
+ }
+
+ public static String getFormattedString(String key, String arg) {
+ return MessageFormat.format(getResourceString(key), new Object[] { arg });
+ }
+
+ public static String getFormattedString(String key, String[] args) {
+ return MessageFormat.format(getResourceString(key), (Object[]) args);
+ }
+
+ public static ResourceBundle getResourceBundle() {
+ return resourceBundle;
+ }
+
+ public static CCorePlugin getDefault() {
+ return plugin;
+ }
+
+ public static void log(Throwable e) {
+ String msg = e.getMessage();
+ if (msg == null) {
+ log("Error", e);
+ } else {
+ log("Error: " + msg, e);
+ }
+ }
+
+ public static void log(String message, Throwable e) {
+ log(createStatus(message, e));
+ }
+
+ public static IStatus createStatus(String message) {
+ return createStatus(message, null);
+ }
+
+ public static IStatus createStatus(String message, Throwable exception) {
+ return new Status(IStatus.ERROR, PLUGIN_ID, message, exception);
+ }
+
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+}
diff --git a/com.google.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties b/com.google.eclipse.cdt.core/src/com/google/eclipse/cdt/internal/core/CCorePluginResources.properties
similarity index 78%
rename from com.google.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties
rename to com.google.eclipse.cdt.core/src/com/google/eclipse/cdt/internal/core/CCorePluginResources.properties
index b49ad65..62d2d05 100644
--- a/com.google.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties
+++ b/com.google.eclipse.cdt.core/src/com/google/eclipse/cdt/internal/core/CCorePluginResources.properties
@@ -4,12 +4,6 @@
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# QNX Software Systems - Initial API and implementation
-# Markus Schorn (Wind River Systems)
-# Anton Leherbauer (Wind River Systems)
-# Anton Gorenkov
###############################################################################
Util.exception.cannotCreatePty=Cannot create pty
Util.exception.cannotSetTerminalSize=Setting terminal size is not supported
diff --git a/com.google.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/com.google.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
deleted file mode 100644
index ed43603..0000000
--- a/com.google.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Markus Schorn (Wind River Systems)
- * Andrew Ferguson (Symbian)
- * Anton Leherbauer (Wind River Systems)
- * oyvind.harboe@zylin.com - http://bugs.eclipse.org/250638
- * Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
- *******************************************************************************/
-package org.eclipse.cdt.core;
-
-import java.util.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-import org.osgi.framework.BundleContext;
-
-import com.ibm.icu.text.MessageFormat;
-
-/**
- * CCorePlugin is the life-cycle owner of the core plug-in, and starting point for access to many core APIs.
- *
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- */
-public class CCorePlugin extends Plugin {
- public static final String PLUGIN_ID = "org.eclipse.cdt.core"; //$NON-NLS-1$
-
- private static CCorePlugin fgCPlugin;
- private static ResourceBundle fgResourceBundle;
-
- // -------- static methods --------
-
- static {
- try {
- fgResourceBundle = ResourceBundle.getBundle("org.eclipse.cdt.internal.core.CCorePluginResources"); //$NON-NLS-1$
- } catch (MissingResourceException x) {
- fgResourceBundle = null;
- }
- }
-
- public static String getResourceString(String key) {
- try {
- return fgResourceBundle.getString(key);
- } catch (MissingResourceException e) {
- return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$
- } catch (NullPointerException e) {
- return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
- public static IWorkspace getWorkspace() {
- return ResourcesPlugin.getWorkspace();
- }
-
- public static String getFormattedString(String key, String arg) {
- return MessageFormat.format(getResourceString(key), new Object[] { arg });
- }
-
- public static String getFormattedString(String key, String[] args) {
- return MessageFormat.format(getResourceString(key), (Object[])args);
- }
-
- public static ResourceBundle getResourceBundle() {
- return fgResourceBundle;
- }
-
- public static CCorePlugin getDefault() {
- return fgCPlugin;
- }
-
-
- /**
- * @see Plugin#shutdown
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- super.stop(context);
- }
-
- /**
- * @see Plugin#startup
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
- }
-
- /**
- * @noreference This constructor is not intended to be referenced by clients.
- */
- public CCorePlugin() {
- super();
- fgCPlugin = this;
- }
-
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
- public static void log(String e) {
- log(createStatus(e));
- }
-
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
- public static void log(Throwable e) {
- String msg= e.getMessage();
- if (msg == null) {
- log("Error", e); //$NON-NLS-1$
- } else {
- log("Error: " + msg, e); //$NON-NLS-1$
- }
- }
-
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
- public static void log(String message, Throwable e) {
- log(createStatus(message, e));
- }
-
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
- public static IStatus createStatus(String msg) {
- return createStatus(msg, null);
- }
-
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
- public static IStatus createStatus(String msg, Throwable e) {
- return new Status(IStatus.ERROR, PLUGIN_ID, msg, e);
- }
-
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
- public static void log(IStatus status) {
- getDefault().getLog().log(status);
- }
-}
diff --git a/com.google.eclipse.cdt.core/utils/com/google/eclipse/cdt/utils/Platform.java b/com.google.eclipse.cdt.core/utils/com/google/eclipse/cdt/utils/Platform.java
new file mode 100644
index 0000000..616e13b
--- /dev/null
+++ b/com.google.eclipse.cdt.core/utils/com/google/eclipse/cdt/utils/Platform.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.cdt.utils;
+
+import java.io.*;
+
+import org.osgi.framework.Bundle;
+
+import com.google.eclipse.cdt.core.CCorePlugin;
+
+public final class Platform {
+ // This class duplicates all of the methods in org.eclipse.core.runtime.Platform
+ // that are used by the CDT. getOSArch() needs a few tweaks because the value returned
+ // by org.eclipse.core.runtime.Platform.getOSArch represents what the JVM thinks the
+ // architecture is. In some cases, we may actually be running on a 64-bit machine,
+ // but the JVM thinks it's running on a 32-bit machine. Without this change, the CDT
+ // will not handle 64-bit executables on some ppc64. This method could easily be
+ // extended to handle other platforms with similar issues.
+ //
+ // Unfortunately, the org.eclipse.core.runtime.Platform is final, so we cannot just
+ // extend it and and then override the getOSArch method, so getBundle and getOS just
+ // encapsulate calls to the same methods in org.eclipse.core.runtime.Platform.
+
+ public static final String OS_LINUX = org.eclipse.core.runtime.Platform.OS_LINUX;
+
+ private static String cachedArch = null;
+
+ public static Bundle getBundle(String symbolicName) {
+ return org.eclipse.core.runtime.Platform.getBundle(symbolicName);
+ }
+
+ public static String getOS() {
+ return org.eclipse.core.runtime.Platform.getOS();
+ }
+
+ public static String getOSArch() {
+ if (cachedArch == null) {
+ String arch = org.eclipse.core.runtime.Platform.getOSArch();
+ if (arch.equals(org.eclipse.core.runtime.Platform.ARCH_PPC)) {
+ // Determine if the platform is actually a ppc64 machine
+ Process unameProcess;
+ String cmd[] = { "uname", "-p" };
+ try {
+ unameProcess = Runtime.getRuntime().exec(cmd);
+ InputStreamReader inputStreamReader = new InputStreamReader(unameProcess.getInputStream());
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+ String unameOutput = bufferedReader.readLine();
+ if (unameOutput != null) {
+ arch = unameOutput;
+ }
+ bufferedReader.close();
+ unameProcess.waitFor(); // otherwise the process becomes a zombie
+ } catch (IOException e) {
+ CCorePlugin.log(e);
+ } catch (InterruptedException exc) {
+ // restore interrupted flag
+ Thread.currentThread().interrupt();
+ }
+ } else if (arch.equals(org.eclipse.core.runtime.Platform.ARCH_X86)) {
+ // Determine if the platform is actually a x86_64 machine
+ Process unameProcess;
+ String cmd[];
+ if (org.eclipse.core.runtime.Platform.OS_WIN32.equals(getOS())) {
+ cmd = new String[] { "cmd", "/d", "/c", "set", "PROCESSOR_ARCHITECTURE" };
+ } else {
+ // We don't use "uname -p" since it returns "unknown" on some Linux systems.
+ cmd = new String[] { "uname", "-m" };
+ }
+ try {
+ unameProcess = Runtime.getRuntime().exec(cmd);
+ unameProcess.getOutputStream().close();
+ unameProcess.getErrorStream().close();
+ InputStreamReader inputStreamReader = new InputStreamReader(unameProcess.getInputStream());
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+ String unameOutput = bufferedReader.readLine();
+ if (unameOutput != null && unameOutput.endsWith("64")) {
+ arch = org.eclipse.core.runtime.Platform.ARCH_X86_64;
+ }
+ bufferedReader.close();
+ unameProcess.waitFor(); // otherwise the process becomes a zombie
+ } catch (IOException e) {
+ CCorePlugin.log(e);
+ } catch (InterruptedException e) {
+ // restore interrupted flag
+ Thread.currentThread().interrupt();
+ }
+ }
+ cachedArch = arch;
+ }
+ return cachedArch;
+ }
+
+ private Platform() {}
+}
diff --git a/com.google.eclipse.cdt.core/utils/com/google/eclipse/cdt/utils/spawner/EnvironmentReader.java b/com.google.eclipse.cdt.core/utils/com/google/eclipse/cdt/utils/spawner/EnvironmentReader.java
new file mode 100644
index 0000000..2f7f390
--- /dev/null
+++ b/com.google.eclipse.cdt.core/utils/com/google/eclipse/cdt/utils/spawner/EnvironmentReader.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.cdt.utils.spawner;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * This class provides environment variables supplied as {@link Properties} class.
+ */
+public final class EnvironmentReader {
+ private static Properties envVars = null;
+ private static Properties envVarsNormalized = null;
+ private static ArrayList<String> rawVars = null;
+
+ private static synchronized void init() {
+ if (envVars == null) {
+ envVars = new Properties();
+ // on Windows environment variable names are case-insensitive
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ envVarsNormalized = new Properties();
+ } else {
+ envVarsNormalized = envVars;
+ }
+ rawVars = new ArrayList<String>();
+ Map<String, String> envMap = System.getenv();
+ for (String var : envMap.keySet()) {
+ String value = envMap.get(var);
+ envVars.setProperty(var, value);
+ if (envVarsNormalized != envVars) {
+ envVarsNormalized.setProperty(var.toUpperCase(), value);
+ }
+ rawVars.add(var + "=" + value);
+ }
+ rawVars.trimToSize();
+ }
+ }
+
+ public static Properties getEnvVars() {
+ init();
+ return (Properties) envVars.clone();
+ }
+
+ public static String getEnvVar(String key) {
+ init();
+ return envVarsNormalized.getProperty(key);
+ }
+
+ private EnvironmentReader() {}
+}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/Platform.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/Platform.java
deleted file mode 100644
index b462cf5..0000000
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/Platform.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - Initial API and implementation (Corey Ashford)
- * Anton Leherbauer (Wind River Systems)
- * Markus Schorn (Wind River Systems)
- *******************************************************************************/
-
-package org.eclipse.cdt.utils;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-import org.eclipse.cdt.core.CCorePlugin;
-import org.osgi.framework.Bundle;
-
-/**
- * @noinstantiate This class is not intended to be instantiated by clients.
- */
-public final class Platform {
-
- // This class duplicates all of the methods in org.eclipse.core.runtime.Platform
- // that are used by the CDT. getOSArch() needs a few tweaks because the value returned
- // by org.eclipse.core.runtime.Platform.getOSArch represents what the JVM thinks the
- // architecture is. In some cases, we may actually be running on a 64-bit machine,
- // but the JVM thinks it's running on a 32-bit machine. Without this change, the CDT
- // will not handle 64-bit executables on some ppc64. This method could easily be
- // extended to handle other platforms with similar issues.
- //
- // Unfortunately, the org.eclipse.core.runtime.Platform is final, so we cannot just
- // extend it and and then override the getOSArch method, so getBundle and getOS just
- // encapsulate calls to the same methods in org.eclipse.core.runtime.Platform.
-
- public static final String OS_LINUX = org.eclipse.core.runtime.Platform.OS_LINUX;
-
- private static String cachedArch = null;
-
- public static Bundle getBundle(String symbolicName) {
- return org.eclipse.core.runtime.Platform.getBundle(symbolicName);
- }
-
- public static String getOS() {
- return org.eclipse.core.runtime.Platform.getOS();
- }
-
- public static String getOSArch() {
- if (cachedArch == null) {
- String arch = org.eclipse.core.runtime.Platform.getOSArch();
- if (arch.equals(org.eclipse.core.runtime.Platform.ARCH_PPC)) {
- // Determine if the platform is actually a ppc64 machine
- Process unameProcess;
- String cmd[] = {"uname", "-p"}; //$NON-NLS-1$//$NON-NLS-2$
-
- try {
- unameProcess = Runtime.getRuntime().exec(cmd);
-
- InputStreamReader inputStreamReader = new InputStreamReader(unameProcess.getInputStream());
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
- String unameOutput= bufferedReader.readLine();
- if (unameOutput != null) {
- arch= unameOutput;
- }
- bufferedReader.close();
- unameProcess.waitFor(); // otherwise the process becomes a zombie
- } catch (IOException e) {
- CCorePlugin.log(e);
- } catch (InterruptedException exc) {
- // restore interrupted flag
- Thread.currentThread().interrupt();
- }
- } else if (arch.equals(org.eclipse.core.runtime.Platform.ARCH_X86)) {
- // Determine if the platform is actually a x86_64 machine
- Process unameProcess;
- String cmd[];
- if (org.eclipse.core.runtime.Platform.OS_WIN32.equals(getOS())) {
- cmd = new String[] {"cmd", "/d", "/c", "set", "PROCESSOR_ARCHITECTURE"}; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
- } else {
- // We don't use "uname -p" since it returns "unknown" on some Linux systems.
- cmd = new String[] {"uname", "-m"}; //$NON-NLS-1$//$NON-NLS-2$
- }
-
- try {
- unameProcess = Runtime.getRuntime().exec(cmd);
- unameProcess.getOutputStream().close();
- unameProcess.getErrorStream().close();
- InputStreamReader inputStreamReader = new InputStreamReader(unameProcess.getInputStream());
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
- String unameOutput = bufferedReader.readLine();
- if (unameOutput != null && unameOutput.endsWith("64")) { //$NON-NLS-1$
- arch= org.eclipse.core.runtime.Platform.ARCH_X86_64;
- }
- bufferedReader.close();
- unameProcess.waitFor(); // otherwise the process becomes a zombie
- } catch (IOException e) {
- CCorePlugin.log(e);
- } catch (InterruptedException exc) {
- // restore interrupted flag
- Thread.currentThread().interrupt();
- }
- }
- cachedArch= arch;
- }
- return cachedArch;
- }
-}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java
index 81a73d5..498c16c 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java
@@ -4,166 +4,144 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
- * Wind River Systems, Inc. - bug 248071
*******************************************************************************/
package org.eclipse.cdt.utils.pty;
import java.io.IOException;
-import org.eclipse.cdt.core.CCorePlugin;
+import com.google.eclipse.cdt.core.CCorePlugin;
/**
* PTY - pseudo terminal support.
*/
public class PTY {
- static final String LIBRARY_NAME = "gpty"; //$NON-NLS-1$
+ static final String LIBRARY_NAME = "gpty";
- final boolean console;
- String slave;
- PTYInputStream in;
- PTYOutputStream out;
- /**
- * NOTE: Field is accessed by the native layer. Do not refactor!
- */
- int master;
+ final boolean console;
+ String slave;
+ PTYInputStream in;
+ PTYOutputStream out;
+ /*
+ * NOTE: Field is accessed by the native layer. Do not refactor!
+ */
+ int master;
- private static boolean hasPTY;
- private static boolean setTerminalSizeErrorAlreadyLogged;
+ private static boolean hasPTY;
+ private static boolean setTerminalSizeErrorAlreadyLogged;
- /**
- * The master fd is used on two streams. We need to wrap the fd so that when stream.close() is called the
- * other stream is disabled.
- */
- public class MasterFD {
+ /**
+ * The master fd is used on two streams. We need to wrap the fd so that when stream.close() is called the other stream
+ * is disabled.
+ */
+ public class MasterFD {
+ public int getFD() {
+ return master;
+ }
- public int getFD() {
- return master;
- }
+ void setFD(int fd) {
+ master = fd;
+ }
+ }
- void setFD(int fd) {
- master = fd;
- }
- }
+ /**
+ * Create PTY for use with Eclipse console. Identical to {@link PTY#PTY(boolean) PTY(true)}.
+ * @throws IOException if something goes wrong.
+ */
+ public PTY() throws IOException {
+ this(true);
+ }
- /**
- * Create PTY for use with Eclipse console. Identical to {@link PTY#PTY(boolean) PTY(true)}.
- */
- public PTY() throws IOException {
- this(true);
- }
+ /**
+ * Create pseudo-terminal.
+ *
+ * <p>
+ * The provided flag indicates whether the pseudo terminal is used with the interactive Eclipse console:
+ * <ul>
+ * <li>If {@code true} the terminal is configured with no echo and stderr is redirected to a pipe instead of the
+ * PTY.</li>
+ * <li>If {@code false} the terminal is configured with echo and stderr is connected to the PTY. This mode is
+ * best suited for use with a proper terminal emulation. Note that this mode might not be supported on all platforms.
+ * Known platforms which support this mode are: <code>linux-x86</code>, <code>linux-x86_64</code>,
+ * <code>solaris-sparc</code>, <code>macosx</code>.</li>
+ * </ul>
+ * </p>
+ *
+ * @param console whether terminal is used with Eclipse console
+ * @throws IOException if the PTY could not be created
+ * @since 5.2
+ */
+ public PTY(boolean console) throws IOException {
+ this.console = console;
- /**
- * Create pseudo terminal.
- *
- * <p>
- * The provided flag indicates whether the pseudo terminal is used with the interactive Eclipse console:
- * <ul>
- * <li>If <code>true</code> the terminal is configured with no echo and stderr is redirected to a pipe
- * instead of the PTY.</li>
- * <li>If <code>false</code> the terminal is configured with echo and stderr is connected to the PTY. This
- * mode is best suited for use with a proper terminal emulation. Note that this mode might not be
- * supported on all platforms. Known platforms which support this mode are: <code>linux-x86</code>,
- * <code>linux-x86_64</code>, <code>solaris-sparc</code>, <code>macosx</code>.</li>
- * </ul>
- * </p>
- *
- * @param console
- * whether terminal is used with Eclipse console
- * @throws IOException
- * if the PTY could not be created
- * @since 5.2
- */
- public PTY(boolean console) throws IOException {
- this.console = console;
+ if (hasPTY) {
+ slave = openMaster(console);
+ }
- if (hasPTY) {
- slave = openMaster(console);
- }
+ if (slave == null) {
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty"));
+ }
- if (slave == null) {
- throw new IOException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$
- }
+ in = new PTYInputStream(new MasterFD());
+ out = new PTYOutputStream(new MasterFD());
+ }
- in = new PTYInputStream(new MasterFD());
- out = new PTYOutputStream(new MasterFD());
- }
+ public String getSlaveName() {
+ return slave;
+ }
- public String getSlaveName() {
- return slave;
- }
+ public MasterFD getMasterFD() {
+ return new MasterFD();
+ }
- public MasterFD getMasterFD() {
- return new MasterFD();
- }
+ /**
+ * @return whether this pseudo terminal is for use with the Eclipse console.
+ */
+ public final boolean isConsole() {
+ return console;
+ }
- /**
- * @return whether this pseudo terminal is for use with the Eclipse console.
- *
- * @since 5.2
- */
- public final boolean isConsole() {
- return console;
- }
+ public PTYOutputStream getOutputStream() {
+ return out;
+ }
- public PTYOutputStream getOutputStream() {
- return out;
- }
+ public PTYInputStream getInputStream() {
+ return in;
+ }
- public PTYInputStream getInputStream() {
- return in;
- }
+ /**
+ * Change terminal window size to given width and height.
+ * <p>
+ * This should only be used when the pseudo terminal is configured for use with a terminal emulation, i.e. when
+ * {@link #isConsole()} returns {@code false}.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This method may not be supported on all platforms. Known platforms which support this method
+ * are: {@code linux-x86}, {@code linux-x86_64}, {@code solaris-sparc}, {@code macosx}.
+ * </p>
+ * @param width the given width.
+ * @param height the given height.
+ */
+ public final void setTerminalSize(int width, int height) {
+ try {
+ change_window_size(master, width, height);
+ } catch (UnsatisfiedLinkError e) {
+ if (!setTerminalSizeErrorAlreadyLogged) {
+ setTerminalSizeErrorAlreadyLogged = true;
+ CCorePlugin.log(CCorePlugin.getResourceString("Util.exception.cannotSetTerminalSize"), e);
+ }
+ }
+ }
- /**
- * Change terminal window size to given width and height.
- * <p>
- * This should only be used when the pseudo terminal is configured for use with a terminal emulation, i.e.
- * when {@link #isConsole()} returns <code>false</code>.
- * </p>
- * <p>
- * <strong>Note:</strong> This method may not be supported on all platforms. Known platforms which support
- * this method are: <code>linux-x86</code>, <code>linux-x86_64</code>, <code>solaris-sparc</code>,
- * <code>macosx</code>.
- * </p>
- *
- * @since 5.2
- */
- public final void setTerminalSize(int width, int height) {
- try {
- change_window_size(master, width, height);
- } catch (UnsatisfiedLinkError ule) {
- if (!setTerminalSizeErrorAlreadyLogged) {
- setTerminalSizeErrorAlreadyLogged = true;
- CCorePlugin.log(
- CCorePlugin.getResourceString("Util.exception.cannotSetTerminalSize"), ule); //$NON-NLS-1$
- }
- }
- }
+ public static boolean isSupported() {
+ return hasPTY;
+ }
- /**
- * @return whether PTY support is available on this platform
- */
- public static boolean isSupported() {
- return hasPTY;
- }
+ native String openMaster(boolean console);
- native String openMaster(boolean console);
+ native int change_window_size(int fdm, int width, int height);
- native int change_window_size(int fdm, int width, int height);
-
- static {
- try {
- System.loadLibrary(LIBRARY_NAME);
- hasPTY = true;
- } catch (SecurityException e) {
- // Comment out it worries the users too much
- // CCorePlugin.log(e);
- } catch (UnsatisfiedLinkError e) {
- // Comment out it worries the users too much
- // CCorePlugin.log(e);
- }
- }
-
+ static {
+ System.loadLibrary(LIBRARY_NAME);
+ hasPTY = true;
+ }
}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYInputStream.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYInputStream.java
index 78e8944..a2f1a1e 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYInputStream.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYInputStream.java
@@ -4,95 +4,73 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
- * Wind River Systems - bug 286162
*******************************************************************************/
package org.eclipse.cdt.utils.pty;
-
import java.io.*;
import org.eclipse.cdt.utils.pty.PTY.MasterFD;
class PTYInputStream extends InputStream {
+ MasterFD master;
- MasterFD master;
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public PTYInputStream(MasterFD fd) {
+ master = fd;
+ }
- /**
- * From a Unix valid file descriptor set a Reader.
- * @param fd file descriptor.
- */
- public PTYInputStream(MasterFD fd) {
- master = fd;
- }
-
- /**
- * Implementation of read for the InputStream.
- *
- * @exception IOException on error.
- */
- @Override
- public int read() throws IOException {
- byte b[] = new byte[1];
- if (1 != read(b, 0, 1)) {
+ /**
+ * Implementation of read for the InputStream.
+ *
+ * @exception IOException on error.
+ */
+ @Override public int read() throws IOException {
+ byte b[] = new byte[1];
+ if (1 != read(b, 0, 1)) {
return -1;
}
- return b[0];
- }
+ return b[0];
+ }
- /**
- * @see InputStream#read(byte[], int, int)
- */
- @Override
- public int read(byte[] buf, int off, int len) throws IOException {
- if (buf == null) {
- throw new NullPointerException();
- } else if ((off < 0) || (off > buf.length)
- || (len < 0) || ((off + len) > buf.length)
- || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- byte[] tmpBuf = new byte[len];
-
- len = read0(master.getFD(), tmpBuf, len);
- if (len <= 0) {
+ @Override public int read(byte[] buf, int off, int len) throws IOException {
+ if (buf == null) {
+ throw new NullPointerException();
+ }
+ if ((off < 0) || (off > buf.length) || (len < 0) || ((off + len) > buf.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len == 0) {
+ return 0;
+ }
+ byte[] tmpBuf = new byte[len];
+ len = read0(master.getFD(), tmpBuf, len);
+ if (len <= 0) {
return -1;
}
+ System.arraycopy(tmpBuf, 0, buf, off, len);
+ return len;
+ }
- System.arraycopy(tmpBuf, 0, buf, off, len);
- return len;
- }
-
- /**
- * Close the Reader
- * @exception IOException on error.
- */
- @Override
- public void close() throws IOException {
- if (master.getFD() == -1) {
+ @Override public void close() throws IOException {
+ if (master.getFD() == -1) {
return;
}
- close0(master.getFD());
- // ignore error on close - see bug 286162
-// if (status == -1)
-// throw new IOException(CCorePlugin.getResourceString("Util.exception.closeError")); //$NON-NLS-1$
- master.setFD(-1);
- }
+ close0(master.getFD());
+ master.setFD(-1);
+ }
- @Override
- protected void finalize() throws IOException {
- close();
- }
+ @Override protected void finalize() throws IOException {
+ close();
+ }
- private native int read0(int fd, byte[] buf, int len) throws IOException;
- private native int close0(int fd) throws IOException;
+ private native int read0(int fd, byte[] buf, int len) throws IOException;
- static {
- System.loadLibrary(PTY.LIBRARY_NAME);
- }
+ private native int close0(int fd) throws IOException;
+ static {
+ System.loadLibrary(PTY.LIBRARY_NAME);
+ }
}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYOutputStream.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYOutputStream.java
index c8eeb82..265fd26 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYOutputStream.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTYOutputStream.java
@@ -4,89 +4,63 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils.pty;
-
import java.io.*;
import org.eclipse.cdt.utils.pty.PTY.MasterFD;
public class PTYOutputStream extends OutputStream {
+ MasterFD master;
- MasterFD master;
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public PTYOutputStream(MasterFD fd) {
+ master = fd;
+ }
- /**
- * From a Unix valid file descriptor set a Reader.
- * @param fd file descriptor.
- */
- public PTYOutputStream(MasterFD fd) {
- master = fd;
- }
-
- /**
- * @see OutputStream#write(byte[], int, int)
- */
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if (
- (off < 0)
- || (off > b.length)
- || (len < 0)
- || ((off + len) > b.length)
- || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- byte[] tmpBuf = new byte[len];
- System.arraycopy(b, off, tmpBuf, off, len);
- write0(master.getFD(), tmpBuf, len);
- }
- /**
- * Implementation of read for the InputStream.
- *
- * @exception IOException on error.
- */
- @Override
- public void write(int b) throws IOException {
- byte[] buf = new byte[1];
- buf[0] = (byte) b;
- write(buf, 0, 1);
- }
-
- /**
- * Close the Reader
- * @exception IOException on error.
- */
- @Override
- public void close() throws IOException {
- if (master.getFD() == -1) {
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
return;
}
- int status = close0(master.getFD());
- if (status == -1)
- {
- throw new IOException("close error"); //$NON-NLS-1$
+ byte[] tmpBuf = new byte[len];
+ System.arraycopy(b, off, tmpBuf, off, len);
+ write0(master.getFD(), tmpBuf, len);
+ }
+
+ @Override public void write(int b) throws IOException {
+ byte[] buf = new byte[1];
+ buf[0] = (byte) b;
+ write(buf, 0, 1);
+ }
+
+ @Override public void close() throws IOException {
+ if (master.getFD() == -1) {
+ return;
}
- master.setFD(-1);
- }
+ int status = close0(master.getFD());
+ if (status == -1) {
+ throw new IOException("Close error");
+ }
+ master.setFD(-1);
+ }
- @Override
- protected void finalize() throws IOException {
- close();
- }
+ @Override protected void finalize() throws IOException {
+ close();
+ }
- private native int write0(int fd, byte[] b, int len) throws IOException;
- private native int close0(int fd) throws IOException;
+ private native int write0(int fd, byte[] b, int len) throws IOException;
- static {
- System.loadLibrary(PTY.LIBRARY_NAME);
- }
+ private native int close0(int fd) throws IOException;
+ static {
+ System.loadLibrary(PTY.LIBRARY_NAME);
+ }
}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/EnvironmentReader.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/EnvironmentReader.java
deleted file mode 100644
index 39c94d8..0000000
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/EnvironmentReader.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 QNX Software Systems and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
- *******************************************************************************/
-package org.eclipse.cdt.utils.spawner;
-
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Properties;
-
-import org.eclipse.core.runtime.Platform;
-
-/**
- * This class provides environment variables supplied as {@link Properties} class.
- *
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- */
-public class EnvironmentReader {
- private static Properties envVars = null;
- private static Properties envVarsNormalized = null;
- private static ArrayList<String> rawVars = null;
-
- private static synchronized void init() {
- if (envVars==null) {
- envVars = new Properties();
- // on Windows environment variable names are case-insensitive
- if (Platform.getOS().equals(Platform.OS_WIN32)) {
- envVarsNormalized = new Properties();
- } else {
- envVarsNormalized = envVars;
- }
- rawVars = new ArrayList<String>();
- Map<String, String> envMap = System.getenv();
- for (String var : envMap.keySet()) {
- String value = envMap.get(var);
- envVars.setProperty(var, value);
- if (envVarsNormalized!=envVars) {
- envVarsNormalized.setProperty(var.toUpperCase(), value);
- }
- rawVars.add(var + "=" + value); //$NON-NLS-1$
- }
- rawVars.trimToSize();
- }
- }
-
- /**
- * @return list of environment variables.
- */
- public static Properties getEnvVars() {
- init();
- return (Properties) envVars.clone();
- }
-
- /**
- * @param key - name of environment variable (without $ sign).
- * @return value of environment variable.
- */
- public static String getEnvVar(String key) {
- init();
- return envVarsNormalized.getProperty(key);
- }
-
- /**
- * @deprecated since CDT 6.1. {@link #getEnvVars()} provides all the data.
- */
- @Deprecated
- public static String[] getRawEnvVars() {
- init();
- return rawVars.toArray(new String[rawVars.size()]);
- }
-}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java
index 1c226a0..a0319d4 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java
@@ -4,103 +4,87 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils.spawner;
-
import java.io.*;
-import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.utils.pty.PTY;
-/**
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- */
+import com.google.eclipse.cdt.core.CCorePlugin;
+
public class ProcessFactory {
+ static private ProcessFactory instance;
- static private ProcessFactory instance;
- private boolean hasSpawner;
- private final Runtime runtime;
+ private boolean hasSpawner;
+ private final Runtime runtime;
- private ProcessFactory() {
- hasSpawner = false;
- String OS = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
- runtime = Runtime.getRuntime();
- try {
- // Spawner does not work for Windows 98 fallback
- if (OS != null && OS.equals("windows 98")) { //$NON-NLS-1$
- hasSpawner = false;
- } else {
- System.loadLibrary(Spawner.LIBRARY_NAME);
- hasSpawner = true;
- }
- } catch (SecurityException e) {
- e.printStackTrace();
- } catch (UnsatisfiedLinkError e) {
- e.printStackTrace();
- }
- }
+ private ProcessFactory() {
+ hasSpawner = false;
+ String OS = System.getProperty("os.name").toLowerCase();
+ runtime = Runtime.getRuntime();
+ // Spawner does not work for Windows 98 fallback
+ if (OS != null && OS.equals("windows 98")) {
+ hasSpawner = false;
+ } else {
+ System.loadLibrary(Spawner.LIBRARY_NAME);
+ hasSpawner = true;
+ }
+ }
- public static ProcessFactory getFactory() {
- if (instance == null) {
+ public static ProcessFactory getFactory() {
+ if (instance == null) {
instance = new ProcessFactory();
}
- return instance;
- }
+ return instance;
+ }
- public Process exec(String cmd) throws IOException {
- if (hasSpawner) {
+ public Process exec(String cmd) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmd);
}
- return runtime.exec(cmd);
- }
+ return runtime.exec(cmd);
+ }
- public Process exec(String[] cmdarray) throws IOException {
- if (hasSpawner) {
+ public Process exec(String[] cmdarray) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmdarray);
}
- return runtime.exec(cmdarray);
- }
+ return runtime.exec(cmdarray);
+ }
- public Process exec(String[] cmdarray, String[] envp) throws IOException {
- if (hasSpawner) {
+ public Process exec(String[] cmdarray, String[] envp) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmdarray, envp);
}
- return runtime.exec(cmdarray, envp);
- }
+ return runtime.exec(cmdarray, envp);
+ }
- public Process exec(String cmd, String[] envp) throws IOException {
- if (hasSpawner) {
+ public Process exec(String cmd, String[] envp) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmd, envp);
}
- return runtime.exec(cmd, envp);
- }
+ return runtime.exec(cmd, envp);
+ }
- public Process exec(String cmd, String[] envp, File dir)
- throws IOException {
- if (hasSpawner) {
+ public Process exec(String cmd, String[] envp, File dir) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmd, envp, dir);
}
- return runtime.exec(cmd, envp, dir);
- }
+ return runtime.exec(cmd, envp, dir);
+ }
- public Process exec(String cmdarray[], String[] envp, File dir)
- throws IOException {
- if (hasSpawner) {
+ public Process exec(String cmdarray[], String[] envp, File dir) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmdarray, envp, dir);
}
- return runtime.exec(cmdarray, envp, dir);
- }
+ return runtime.exec(cmdarray, envp, dir);
+ }
- public Process exec(String cmdarray[], String[] envp, File dir, PTY pty)
- throws IOException {
- if (hasSpawner) {
+ public Process exec(String cmdarray[], String[] envp, File dir, PTY pty) throws IOException {
+ if (hasSpawner) {
return new Spawner(cmdarray, envp, dir, pty);
}
- throw new UnsupportedOperationException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$
- }
+ throw new UnsupportedOperationException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty"));
+ }
}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java
index acdf49c..4e2024e 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java
@@ -4,523 +4,435 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
- * Wind River Systems - bug 248071, bug 286162
*******************************************************************************/
package org.eclipse.cdt.utils.spawner;
-
import java.io.*;
import java.util.StringTokenizer;
-import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;
+import com.google.eclipse.cdt.core.CCorePlugin;
+
public class Spawner extends Process {
- static final String LIBRARY_NAME = "gspawner"; //$NON-NLS-1$
+ static final String LIBRARY_NAME = "gspawner";
public int NOOP = 0;
- public int HUP = 1;
- public int KILL = 9;
- public int TERM = 15;
+ public int HUP = 1;
+ public int KILL = 9;
+ public int TERM = 15;
- /**
- * On Windows, what this does is far from easy to explain.
- * Some of the logic is in the JNI code, some in the spawner.exe code.
- *
- * <ul>
- * <li>If the process this is being raised against was launched by us (the Spawner)
- * <ul>
- * <li>If the process is a cygwin program (has the cygwin1.dll loaded), then issue a 'kill -SIGINT'. If
- * the 'kill' utility isn't available, send the process a CTRL-C
- * <li>If the process is <i>not</i> a cygwin program, send the process a CTRL-C
- * </ul>
- * <li>If the process this is being raised against was <i>not</i> launched by us, use
- * DebugBreakProcess to interrupt it (sending a CTRL-C is easy only if we share a console
- * with the target process)
- * </ul>
- *
- * On non-Windows, raising this just raises a POSIX SIGINT
- *
- */
- public int INT = 2;
+ /**
+ * On Windows, what this does is far from easy to explain. Some of the logic is in the JNI code, some in the
+ * spawner.exe code.
+ *
+ * <ul>
+ * <li>If the process this is being raised against was launched by us (the Spawner)
+ * <ul>
+ * <li>If the process is a cygwin program (has the cygwin1.dll loaded), then issue a 'kill -SIGINT'. If the 'kill'
+ * utility isn't available, send the process a CTRL-C
+ * <li>If the process is <i>not</i> a cygwin program, send the process a CTRL-C
+ * </ul>
+ * <li>If the process this is being raised against was <i>not</i> launched by us, use DebugBreakProcess to interrupt
+ * it (sending a CTRL-C is easy only if we share a console with the target process)
+ * </ul>
+ *
+ * On non-Windows, raising this just raises a POSIX SIGINT
+ *
+ */
+ public int INT = 2;
- /**
- * A fabricated signal number for use on Windows only. Tells the starter program to send a CTRL-C
- * regardless of whether the process is a Cygwin one or not.
- *
- * @since 5.2
- */
- public int CTRLC = 1000; // arbitrary high number to avoid collision
+ /**
+ * A fabricated signal number for use on Windows only. Tells the starter program to send a CTRL-C regardless of
+ * whether the process is a Cygwin one or not.
+ *
+ * @since 5.2
+ */
+ public int CTRLC = 1000; // arbitrary high number to avoid collision
- int pid = 0;
- int status;
- final int[] fChannels = new int[3];
- boolean isDone;
- OutputStream out;
- InputStream in;
- InputStream err;
- private PTY fPty;
+ int pid = 0;
+ int status;
+ final int[] fChannels = new int[3];
+ boolean isDone;
+ OutputStream out;
+ InputStream in;
+ InputStream err;
+ private PTY fPty;
- public Spawner(String command, boolean bNoRedirect) throws IOException {
- StringTokenizer tokenizer = new StringTokenizer(command);
- String[] cmdarray = new String[tokenizer.countTokens()];
- for (int n = 0; tokenizer.hasMoreTokens(); n++) {
+ public Spawner(String command, boolean bNoRedirect) throws IOException {
+ StringTokenizer tokenizer = new StringTokenizer(command);
+ String[] cmdarray = new String[tokenizer.countTokens()];
+ for (int n = 0; tokenizer.hasMoreTokens(); n++) {
cmdarray[n] = tokenizer.nextToken();
}
- if (bNoRedirect) {
- exec_detached(cmdarray, new String[0], "."); //$NON-NLS-1$
+ if (bNoRedirect) {
+ exec_detached(cmdarray, new String[0], ".");
+ } else {
+ exec(cmdarray, new String[0], ".");
}
- else {
- exec(cmdarray, new String[0], "."); //$NON-NLS-1$
+ }
+
+ protected Spawner(String[] command, String[] environment, File workingDirectory) throws IOException {
+ String dirpath = ".";
+ if (workingDirectory != null) {
+ dirpath = workingDirectory.getAbsolutePath();
}
- }
- /**
- * Executes the specified command and arguments in a separate process with the
- * specified environment and working directory.
- **/
- protected Spawner(String[] cmdarray, String[] envp, File dir) throws IOException {
- String dirpath = "."; //$NON-NLS-1$
- if (dir != null) {
+ exec(command, environment, dirpath);
+ }
+
+ protected Spawner(String[] cmdarray, String[] envp, File dir, PTY pty) throws IOException {
+ String dirpath = ".";
+ if (dir != null) {
dirpath = dir.getAbsolutePath();
}
- exec(cmdarray, envp, dirpath);
- }
+ fPty = pty;
+ exec_pty(cmdarray, envp, dirpath, pty);
+ }
- protected Spawner(String[] cmdarray, String[] envp, File dir, PTY pty) throws IOException {
- String dirpath = "."; //$NON-NLS-1$
- if (dir != null) {
- dirpath = dir.getAbsolutePath();
- }
- fPty = pty;
- exec_pty(cmdarray, envp, dirpath, pty);
- }
- /**
- * Executes the specified string command in a separate process.
- **/
- protected Spawner(String command) throws IOException {
- this(command, null);
- }
+ protected Spawner(String command) throws IOException {
+ this(command, null);
+ }
- /**
- * Executes the specified command and arguments in a separate process.
- **/
- protected Spawner(String[] cmdarray) throws IOException {
- this(cmdarray, null);
- }
+ protected Spawner(String[] command) throws IOException {
+ this(command, null);
+ }
- /**
- * Executes the specified command and arguments in a separate process with the
- * specified environment.
- **/
- protected Spawner(String[] cmdarray, String[] envp) throws IOException {
- this(cmdarray, envp, null);
- }
+ protected Spawner(String[] command, String[] environment) throws IOException {
+ this(command, environment, null);
+ }
- /**
- * Executes the specified string command in a separate process with the specified
- * environment.
- **/
- protected Spawner(String cmd, String[] envp) throws IOException {
- this(cmd, envp, null);
- }
+ protected Spawner(String command, String[] environment) throws IOException {
+ this(command, environment, null);
+ }
- /**
- * Executes the specified string command in a separate process with the specified
- * environment and working directory.
- **/
- protected Spawner(String command, String[] envp, File dir) throws IOException {
- StringTokenizer tokenizer = new StringTokenizer(command);
- String[] cmdarray = new String[tokenizer.countTokens()];
- for (int n = 0; tokenizer.hasMoreTokens(); n++) {
+ protected Spawner(String command, String[] environment, File workingDirectory) throws IOException {
+ StringTokenizer tokenizer = new StringTokenizer(command);
+ String[] cmdarray = new String[tokenizer.countTokens()];
+ for (int n = 0; tokenizer.hasMoreTokens(); n++) {
cmdarray[n] = tokenizer.nextToken();
}
- String dirpath = "."; //$NON-NLS-1$
- if (dir != null) {
- dirpath = dir.getAbsolutePath();
+ String dirpath = ".";
+ if (workingDirectory != null) {
+ dirpath = workingDirectory.getAbsolutePath();
}
- exec(cmdarray, envp, dirpath);
- }
+ exec(cmdarray, environment, dirpath);
+ }
- @Override
- protected void finalize() throws Throwable {
- closeUnusedStreams();
- }
+ @Override protected void finalize() throws Throwable {
+ closeUnusedStreams();
+ }
- /**
- * See java.lang.Process#getInputStream ();
- * The client is responsible for closing the stream explicitly.
- **/
- @Override
- public synchronized InputStream getInputStream() {
- if(null == in) {
- if (fPty != null) {
- in = fPty.getInputStream();
- } else {
- in = new SpawnerInputStream(fChannels[1]);
- }
- }
- return in;
- }
+ /**
+ * See java.lang.Process#getInputStream (); The client is responsible for closing the stream explicitly.
+ **/
+ @Override public synchronized InputStream getInputStream() {
+ if (null == in) {
+ if (fPty != null) {
+ in = fPty.getInputStream();
+ } else {
+ in = new SpawnerInputStream(fChannels[1]);
+ }
+ }
+ return in;
+ }
- /**
- * See java.lang.Process#getOutputStream ();
- * The client is responsible for closing the stream explicitly.
- **/
- @Override
- public synchronized OutputStream getOutputStream() {
- if(null == out) {
- if (fPty != null) {
- out = fPty.getOutputStream();
- } else {
- out = new SpawnerOutputStream(fChannels[0]);
- }
- }
- return out;
- }
+ /**
+ * See java.lang.Process#getOutputStream (); The client is responsible for closing the stream explicitly.
+ **/
+ @Override public synchronized OutputStream getOutputStream() {
+ if (null == out) {
+ if (fPty != null) {
+ out = fPty.getOutputStream();
+ } else {
+ out = new SpawnerOutputStream(fChannels[0]);
+ }
+ }
+ return out;
+ }
- /**
- * See java.lang.Process#getErrorStream ();
- * The client is responsible for closing the stream explicitly.
- **/
- @Override
- public synchronized InputStream getErrorStream() {
- if(null == err) {
- if (fPty != null && !fPty.isConsole()) {
- // If PTY is used and it's not in "Console" mode, then stderr is
- // redirected to the PTY's output stream. Therefore, return a
- // dummy stream for error stream.
- err = new InputStream() {
- @Override
- public int read() throws IOException {
- return -1;
- }
- };
- } else {
- err = new SpawnerInputStream(fChannels[2]);
- }
- }
- return err;
- }
+ /**
+ * See java.lang.Process#getErrorStream (); The client is responsible for closing the stream explicitly.
+ **/
+ @Override public synchronized InputStream getErrorStream() {
+ if (null == err) {
+ if (fPty != null && !fPty.isConsole()) {
+ // If PTY is used and it's not in "Console" mode, then stderr is
+ // redirected to the PTY's output stream. Therefore, return a
+ // dummy stream for error stream.
+ err = new InputStream() {
+ @Override public int read() throws IOException {
+ return -1;
+ }
+ };
+ } else {
+ err = new SpawnerInputStream(fChannels[2]);
+ }
+ }
+ return err;
+ }
- /**
- * See java.lang.Process#waitFor ();
- **/
- @Override
- public synchronized int waitFor() throws InterruptedException {
- while (!isDone) {
- wait();
- }
+ /**
+ * See java.lang.Process#waitFor ();
+ **/
+ @Override public synchronized int waitFor() throws InterruptedException {
+ while (!isDone) {
+ wait();
+ }
- // For situations where the user does not call destroy(),
- // we try to kill the streams that were not used here.
- // We check for streams that were not created, we create
- // them to attach to the pipes, and then we close them
- // to release the pipes.
- // Streams that were created by the client need to be
- // closed by the client itself.
- //
- // But 345164
- closeUnusedStreams();
- return status;
- }
+ // For situations where the user does not call destroy(),
+ // we try to kill the streams that were not used here.
+ // We check for streams that were not created, we create
+ // them to attach to the pipes, and then we close them
+ // to release the pipes.
+ // Streams that were created by the client need to be
+ // closed by the client itself.
+ //
+ // But 345164
+ closeUnusedStreams();
+ return status;
+ }
- /**
- * See java.lang.Process#exitValue ();
- **/
- @Override
- public synchronized int exitValue() {
- if (!isDone) {
- throw new IllegalThreadStateException("Process not Terminated"); //$NON-NLS-1$
- }
- return status;
- }
+ /**
+ * See java.lang.Process#exitValue ();
+ **/
+ @Override public synchronized int exitValue() {
+ if (!isDone) {
+ throw new IllegalThreadStateException("Process not Terminated");
+ }
+ return status;
+ }
- /**
- * See java.lang.Process#destroy ();
- *
- * Clients are responsible for explicitly closing any streams
- * that they have requested through
- * getErrorStream(), getInputStream() or getOutputStream()
- **/
- @Override
- public synchronized void destroy() {
- // Sends the TERM
- terminate();
+ /**
+ * See java.lang.Process#destroy ();
+ *
+ * Clients are responsible for explicitly closing any streams that they have requested through getErrorStream(),
+ * getInputStream() or getOutputStream()
+ **/
+ @Override public synchronized void destroy() {
+ // Sends the TERM
+ terminate();
- // Close the streams on this side.
- //
- // We only close the streams that were
- // never used by any client.
- // So, if the stream was not created yet,
- // we create it ourselves and close it
- // right away, so as to release the pipe.
- // Note that even if the stream was never
- // created, the pipe has been allocated in
- // native code, so we need to create the
- // stream and explicitly close it.
- //
- // We don't close streams the clients have
- // created because we don't know when the
- // client will be finished using them.
- // It is up to the client to close those
- // streams.
- //
- // But 345164
- closeUnusedStreams();
+ // Close the streams on this side.
+ //
+ // We only close the streams that were
+ // never used by any client.
+ // So, if the stream was not created yet,
+ // we create it ourselves and close it
+ // right away, so as to release the pipe.
+ // Note that even if the stream was never
+ // created, the pipe has been allocated in
+ // native code, so we need to create the
+ // stream and explicitly close it.
+ //
+ // We don't close streams the clients have
+ // created because we don't know when the
+ // client will be finished using them.
+ // It is up to the client to close those
+ // streams.
+ //
+ // But 345164
+ closeUnusedStreams();
- // Grace before using the heavy gone.
- if (!isDone) {
- try {
- wait(1000);
- } catch (InterruptedException e) {
- }
- }
- if (!isDone) {
- kill();
- }
- }
+ // Grace before using the heavy gone.
+ if (!isDone) {
+ try {
+ wait(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ if (!isDone) {
+ kill();
+ }
+ }
- /**
- * On Windows, interrupt the spawned program by using Cygwin's utility 'kill -SIGINT' if it's a Cgywin
- * program, otherwise send it a CTRL-C. If Cygwin's 'kill' command is not available, send a CTRL-C. On
- * linux, interrupt it by raising a SIGINT.
- */
- public int interrupt() {
- return raise(pid, INT);
- }
+ public int interrupt() {
+ return raise(pid, INT);
+ }
- /**
- * On Windows, interrupt the spawned program by send it a CTRL-C (even if it's a Cygwin program). On
- * linux, interrupt it by raising a SIGINT.
- *
- * @since 5.2
- */
- public int interruptCTRLC() {
- if (Platform.getOS().equals(Platform.OS_WIN32)) {
- return raise(pid, CTRLC);
+ public int interruptCTRLC() {
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ return raise(pid, CTRLC);
+ }
+ return interrupt();
+ }
+
+ public int hangup() {
+ return raise(pid, HUP);
+ }
+
+ public int kill() {
+ return raise(pid, KILL);
+ }
+
+ public int terminate() {
+ return raise(pid, TERM);
+ }
+
+ public boolean isRunning() {
+ return (raise(pid, NOOP) == 0);
+ }
+
+ private void exec(String[] cmdarray, String[] envp, String dirpath) throws IOException {
+ String command = cmdarray[0];
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ s.checkExec(command);
+ }
+ if (envp == null) {
+ envp = new String[0];
+ }
+ Reaper reaper = new Reaper(cmdarray, envp, dirpath);
+ reaper.setDaemon(true);
+ reaper.start();
+ // Wait until the subprocess is started or error.
+ synchronized (this) {
+ while (pid == 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
}
- else {
- return interrupt();
+ }
+ }
+ // Check for errors.
+ if (pid == -1) {
+ throw new IOException(reaper.getErrorMessage());
+ }
+ }
+
+ private void exec_pty(String[] command, String[] environment, String workingDirectory, PTY pty) throws IOException {
+ String cmd = command[0];
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ s.checkExec(cmd);
+ }
+ if (environment == null) {
+ environment = new String[0];
+ }
+ final String slaveName = pty.getSlaveName();
+ final int masterFD = pty.getMasterFD().getFD();
+ final boolean console = pty.isConsole();
+ // int fdm = pty.get
+ Reaper reaper = new Reaper(command, environment, workingDirectory) {
+ @Override int execute(String[] cmd, String[] env, String dir, int[] channels) throws IOException {
+ return exec2(cmd, env, dir, channels, slaveName, masterFD, console);
+ }
+ };
+ reaper.setDaemon(true);
+ reaper.start();
+ // Wait until the subprocess is started or error.
+ synchronized (this) {
+ while (pid == 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
}
- }
+ }
+ }
+ if (pid == -1) {
+ throw new IOException("Exec_tty error:" + reaper.getErrorMessage());
+ }
+ }
- public int hangup() {
- return raise(pid, HUP);
- }
-
- public int kill() {
- return raise(pid, KILL);
- }
-
- public int terminate() {
- return raise(pid, TERM);
- }
-
- public boolean isRunning() {
- return (raise(pid, NOOP) == 0);
- }
-
- private void exec(String[] cmdarray, String[] envp, String dirpath) throws IOException {
- String command = cmdarray[0];
- SecurityManager s = System.getSecurityManager();
- if (s != null) {
+ public void exec_detached(String[] cmdarray, String[] envp, String dirpath) throws IOException {
+ String command = cmdarray[0];
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
s.checkExec(command);
}
- if (envp == null) {
+ if (envp == null) {
envp = new String[0];
}
-
- Reaper reaper = new Reaper(cmdarray, envp, dirpath);
- reaper.setDaemon(true);
- reaper.start();
-
- // Wait until the subprocess is started or error.
- synchronized (this) {
- while (pid == 0) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
-
- // Check for errors.
- if (pid == -1) {
- throw new IOException(reaper.getErrorMessage());
- }
- }
-
- private void exec_pty(String[] cmdarray, String[] envp, String dirpath, PTY pty) throws IOException {
- String command = cmdarray[0];
- SecurityManager s = System.getSecurityManager();
- if (s != null) {
- s.checkExec(command);
+ pid = exec1(cmdarray, envp, dirpath);
+ if (pid == -1) {
+ throw new IOException("Exec error");
}
- if (envp == null) {
- envp = new String[0];
- }
+ fChannels[0] = -1;
+ fChannels[1] = -1;
+ fChannels[2] = -1;
+ }
- final String slaveName = pty.getSlaveName();
- final int masterFD = pty.getMasterFD().getFD();
- final boolean console = pty.isConsole();
- //int fdm = pty.get
- Reaper reaper = new Reaper(cmdarray, envp, dirpath) {
- /* (non-Javadoc)
- * @see org.eclipse.cdt.utils.spawner.Spawner.Reaper#execute(java.lang.String[], java.lang.String[], java.lang.String, int[])
- */
- @Override
- int execute(String[] cmd, String[] env, String dir, int[] channels) throws IOException {
- return exec2(cmd, env, dir, channels, slaveName, masterFD, console);
- }
- };
- reaper.setDaemon(true);
- reaper.start();
-
- // Wait until the subprocess is started or error.
- synchronized (this) {
- while (pid == 0) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
-
- // Check for errors.
- if (pid == -1) {
- throw new IOException("Exec_tty error:" + reaper.getErrorMessage()); //$NON-NLS-1$
- }
- }
-
- public void exec_detached(String[] cmdarray, String[] envp, String dirpath) throws IOException {
- String command = cmdarray[0];
- SecurityManager s = System.getSecurityManager();
- if (s != null) {
- s.checkExec(command);
- }
-
- if (envp == null) {
- envp = new String[0];
- }
- pid = exec1(cmdarray, envp, dirpath);
- if (pid == -1) {
- throw new IOException("Exec error"); //$NON-NLS-1$
- }
- fChannels[0] = -1;
- fChannels[1] = -1;
- fChannels[2] = -1;
- }
-
- /**
- * Close any streams not used by clients.
- */
- private synchronized void closeUnusedStreams() {
- try {
- if(null == err) {
+ private synchronized void closeUnusedStreams() {
+ try {
+ if (null == err) {
getErrorStream().close();
}
- } catch (IOException e) {}
- try {
- if(null == in) {
+ } catch (IOException e) {}
+ try {
+ if (null == in) {
getInputStream().close();
}
- } catch (IOException e) {}
- try {
- if(null == out) {
+ } catch (IOException e) {}
+ try {
+ if (null == out) {
getOutputStream().close();
}
- } catch (IOException e) {}
- }
+ } catch (IOException e) {}
+ }
- /**
- * Native method use in normal exec() calls.
- */
- native int exec0( String[] cmdarray, String[] envp, String dir, int[] chan) throws IOException;
+ native int exec0(String[] cmdarray, String[] envp, String dir, int[] chan) throws IOException;
- /**
- * Native method use in no redirect meaning to streams will created.
- */
- native int exec1( String[] cmdarray, String[] envp, String dir) throws IOException;
+ native int exec1(String[] cmdarray, String[] envp, String dir) throws IOException;
- /**
- * Native method when executing with a terminal emulation.
- */
- native int exec2( String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD, boolean console) throws IOException;
+ native int exec2(String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD,
+ boolean console) throws IOException;
- /**
- * Native method to drop a signal on the process with pid.
- */
- public native int raise(int processID, int sig);
+ public native int raise(int processID, int sig);
- /*
- * Native method to wait(3) for process to terminate.
- */
- native int waitFor(int processID);
+ native int waitFor(int processID);
- static {
- try {
- System.loadLibrary(LIBRARY_NAME);
- } catch (SecurityException e) {
- CCorePlugin.log(e);
- } catch (UnsatisfiedLinkError e) {
- CCorePlugin.log(e);
- }
- }
+ static {
+ System.loadLibrary(LIBRARY_NAME);
+ }
- // Spawn a thread to handle the forking and waiting
- // We do it this way because on linux the SIGCHLD is
- // send to the one thread. So do the forking and
- // the wait in the same thread.
- class Reaper extends Thread {
- String[] fCmdarray;
- String[] fEnvp;
- String fDirpath;
- volatile Throwable fException;
+ // Spawn a thread to handle the forking and waiting.
+ // We do it this way because on linux the SIGCHLD is send to the one thread. So do the forking and then wait in the
+ // same thread.
+ class Reaper extends Thread {
+ String[] command;
+ String[] environment;
+ String dirPath;
+ volatile Throwable exception;
- public Reaper(String[] array, String[] env, String dir) {
- super("Spawner Reaper"); //$NON-NLS-1$
- fCmdarray = array;
- fEnvp = env;
- fDirpath = dir;
- fException = null;
- }
+ public Reaper(String[] command, String[] environment, String dirPath) {
+ super("Spawner Reaper");
+ this.command = command;
+ this.environment = environment;
+ this.dirPath = dirPath;
+ exception = null;
+ }
- int execute(String[] cmdarray, String[] envp, String dir, int[] channels) throws IOException {
- return exec0(cmdarray, envp, dir, channels);
- }
+ int execute(String[] cmdarray, String[] envp, String dir, int[] channels) throws IOException {
+ return exec0(cmdarray, envp, dir, channels);
+ }
- @Override
- public void run() {
- try {
- pid = execute(fCmdarray, fEnvp, fDirpath, fChannels);
- } catch (Exception e) {
- pid = -1;
- fException= e;
- }
+ @Override public void run() {
+ try {
+ pid = execute(command, environment, dirPath, fChannels);
+ } catch (Exception e) {
+ pid = -1;
+ exception = e;
+ }
+ // Tell spawner that the process started.
+ synchronized (Spawner.this) {
+ Spawner.this.notifyAll();
+ }
+ if (pid != -1) {
+ // Sync with spawner and notify when done.
+ status = waitFor(pid);
+ synchronized (Spawner.this) {
+ isDone = true;
+ Spawner.this.notifyAll();
+ }
+ }
+ }
- // Tell spawner that the process started.
- synchronized (Spawner.this) {
- Spawner.this.notifyAll();
- }
-
- if (pid != -1) {
- // Sync with spawner and notify when done.
- status = waitFor(pid);
- synchronized (Spawner.this) {
- isDone = true;
- Spawner.this.notifyAll();
- }
- }
- }
-
- public String getErrorMessage() {
- final String reason= fException != null ? fException.getMessage() : "Unknown reason"; //$NON-NLS-1$
- return NLS.bind(CCorePlugin.getResourceString("Util.error.cannotRun"), fCmdarray[0], reason); //$NON-NLS-1$
- }
- }
+ public String getErrorMessage() {
+ final String reason = exception != null ? exception.getMessage() : "Unknown reason";
+ return NLS.bind(CCorePlugin.getResourceString("Util.error.cannotRun"), command[0], reason);
+ }
+ }
}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java
index 9efecbd..dd1e16e 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java
@@ -4,116 +4,84 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils.spawner;
-
import java.io.*;
-import org.eclipse.cdt.core.CCorePlugin;
+import com.google.eclipse.cdt.core.CCorePlugin;
-/**
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- */
class SpawnerInputStream extends InputStream {
- private int fd;
+ private int fd;
- /**
- * From a Unix valid file descriptor set a Reader.
- * @param fd file descriptor.
- */
- public SpawnerInputStream(int fd) {
- this.fd = fd;
- }
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public SpawnerInputStream(int fd) {
+ this.fd = fd;
+ }
- /**
- * Implementation of read for the InputStream.
- *
- * @exception IOException on error.
- */
- @Override
- public int read() throws IOException {
- byte b[] = new byte[1];
- if (1 != read(b, 0, 1)) {
+ @Override public int read() throws IOException {
+ byte b[] = new byte[1];
+ if (1 != read(b, 0, 1)) {
return -1;
}
- return b[0];
- }
+ return b[0];
+ }
- /**
- * @see InputStream#read(byte[], int, int)
- */
- @Override
- public int read(byte[] buf, int off, int len) throws IOException {
- if (buf == null) {
- throw new NullPointerException();
- } else if (
- (off < 0)
- || (off > buf.length)
- || (len < 0)
- || ((off + len) > buf.length)
- || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- byte[] tmpBuf = off > 0 ? new byte[len] : buf;
+ @Override public int read(byte[] buf, int off, int len) throws IOException {
+ if (buf == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > buf.length) || (len < 0) || ((off + len) > buf.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ byte[] tmpBuf = off > 0 ? new byte[len] : buf;
- len = read0(fd, tmpBuf, len);
- if (len <= 0) {
+ len = read0(fd, tmpBuf, len);
+ if (len <= 0) {
return -1;
}
- if (tmpBuf != buf) {
- System.arraycopy(tmpBuf, 0, buf, off, len);
- }
- return len;
- }
+ if (tmpBuf != buf) {
+ System.arraycopy(tmpBuf, 0, buf, off, len);
+ }
+ return len;
+ }
- /**
- * Close the Reader
- * @exception IOException on error.
- */
- @Override
- public void close() throws IOException {
- if (fd == -1) {
+ @Override public void close() throws IOException {
+ if (fd == -1) {
return;
}
- int status = close0(fd);
- if (status == -1)
- {
- throw new IOException(CCorePlugin.getResourceString("Util.exception.closeError")); //$NON-NLS-1$
+ int status = close0(fd);
+ if (status == -1) {
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.closeError"));
}
- fd = -1;
- }
+ fd = -1;
+ }
- @Override
- public int available() throws IOException {
- try {
- return available0(fd);
- }
- catch (UnsatisfiedLinkError e) {
- // for those platforms that do not implement available0
- return super.available();
- }
- }
+ @Override public int available() throws IOException {
+ try {
+ return available0(fd);
+ } catch (UnsatisfiedLinkError e) {
+ // for those platforms that do not implement available0
+ return super.available();
+ }
+ }
- @Override
- protected void finalize() throws IOException {
- close();
- }
+ @Override protected void finalize() throws IOException {
+ close();
+ }
- private native int read0(int fileDesc, byte[] buf, int len) throws IOException;
- private native int close0(int fileDesc) throws IOException;
- private native int available0(int fileDesc) throws IOException;
+ private native int read0(int fileDesc, byte[] buf, int len) throws IOException;
- static {
- System.loadLibrary(Spawner.LIBRARY_NAME);
- }
+ private native int close0(int fileDesc) throws IOException;
+ private native int available0(int fileDesc) throws IOException;
+ static {
+ System.loadLibrary(Spawner.LIBRARY_NAME);
+ }
}
diff --git a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerOutputStream.java b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerOutputStream.java
index c5d6c9c..7ecc61e 100644
--- a/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerOutputStream.java
+++ b/com.google.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerOutputStream.java
@@ -4,90 +4,63 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils.spawner;
-
import java.io.*;
-/**
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- */
public class SpawnerOutputStream extends OutputStream {
- private int fd;
+ private int fd;
- /**
- * From a Unix valid file descriptor set a Reader.
- * @param fd file descriptor.
- */
- public SpawnerOutputStream(int fd) {
- this.fd = fd;
- }
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public SpawnerOutputStream(int fd) {
+ this.fd = fd;
+ }
- /**
- * @see OutputStream#write(byte[], int, int)
- */
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if (
- (off < 0)
- || (off > b.length)
- || (len < 0)
- || ((off + len) > b.length)
- || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- byte[] tmpBuf = new byte[len];
- System.arraycopy(b, off, tmpBuf, off, len);
- write0(fd, tmpBuf, len);
- }
- /**
- * Implementation of read for the InputStream.
- *
- * @exception IOException on error.
- */
- @Override
- public void write(int b) throws IOException {
- byte[] buf = new byte[1];
- buf[0] = (byte) b;
- write(buf, 0, 1);
- }
-
- /**
- * Close the Reader
- * @exception IOException on error.
- */
- @Override
- public void close() throws IOException {
- if (fd == -1) {
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len == 0) {
return;
}
- int status = close0(fd);
- if (status == -1)
- {
- throw new IOException("close error"); //$NON-NLS-1$
+ byte[] tmpBuf = new byte[len];
+ System.arraycopy(b, off, tmpBuf, off, len);
+ write0(fd, tmpBuf, len);
+ }
+
+ @Override public void write(int b) throws IOException {
+ byte[] buf = new byte[1];
+ buf[0] = (byte) b;
+ write(buf, 0, 1);
+ }
+
+ @Override public void close() throws IOException {
+ if (fd == -1) {
+ return;
}
- fd = -1;
- }
+ int status = close0(fd);
+ if (status == -1) {
+ throw new IOException("close error");
+ }
+ fd = -1;
+ }
- @Override
- protected void finalize() throws IOException {
- close();
- }
+ @Override protected void finalize() throws IOException {
+ close();
+ }
- private native int write0(int fd, byte[] b, int len) throws IOException;
- private native int close0(int fd);
+ private native int write0(int fd, byte[] b, int len) throws IOException;
- static {
- System.loadLibrary(Spawner.LIBRARY_NAME);
- }
+ private native int close0(int fd);
+ static {
+ System.loadLibrary(Spawner.LIBRARY_NAME);
+ }
}
diff --git a/com.google.eclipse.terminal.local/META-INF/MANIFEST.MF b/com.google.eclipse.terminal.local/META-INF/MANIFEST.MF
index 1719844..fa69e1f 100644
--- a/com.google.eclipse.terminal.local/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.terminal.local/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: Terminal
Bundle-SymbolicName: com.google.eclipse.terminal.local;singleton:=true
-Bundle-Version: 1.0.0.qualifier
+Bundle-Version: 1.1.0.qualifier
Bundle-Activator: com.google.eclipse.terminal.local.Activator
Bundle-Vendor: Google, Inc.
Require-Bundle: org.eclipse.ui,
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java
index c1d40ac..deab4a2 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java
@@ -8,9 +8,10 @@
*/
package com.google.eclipse.terminal.local;
-import static com.google.eclipse.terminal.local.ImageKeys.*;
import static org.eclipse.core.runtime.IStatus.*;
+import static com.google.eclipse.terminal.local.ImageKeys.*;
+
import java.net.URL;
import org.eclipse.core.runtime.*;
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/LocalTerminalConnector.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/LocalTerminalConnector.java
index 3f9cffa..9da4a52 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/LocalTerminalConnector.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/LocalTerminalConnector.java
@@ -8,13 +8,14 @@
*/
package com.google.eclipse.terminal.local.core.connector;
+import static org.eclipse.core.runtime.IStatus.*;
+
+import static com.google.eclipse.cdt.utils.Platform.*;
import static com.google.eclipse.terminal.local.Activator.*;
import static com.google.eclipse.terminal.local.core.connector.Messages.*;
import static com.google.eclipse.terminal.local.core.connector.PseudoTerminal.isPlatformSupported;
import static com.google.eclipse.terminal.local.util.Platform.*;
-import static org.eclipse.cdt.utils.Platform.*;
-import static org.eclipse.core.runtime.IStatus.*;
-import static org.eclipse.tm.internal.terminal.provisional.api.TerminalState.*;
+import static com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState.*;
import java.io.*;
@@ -23,9 +24,10 @@
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.internal.core.StreamsProxy;
import org.eclipse.osgi.util.NLS;
-import org.eclipse.tm.internal.terminal.connector.TerminalConnector;
-import org.eclipse.tm.internal.terminal.provisional.api.*;
-import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
+
+import com.google.eclipse.tm.internal.terminal.connector.TerminalConnector;
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
+import com.google.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorDelegate;
/**
* Connector to local terminal.
@@ -33,7 +35,7 @@
* @author alruiz@google.com (Alex Ruiz)
*/
@SuppressWarnings("restriction") // StreamsProxy is internal API
-public class LocalTerminalConnector extends TerminalConnectorImpl implements LifeCycleListener {
+public class LocalTerminalConnector extends TerminalConnectorDelegate implements LifeCycleListener {
private static final String ID = "com.google.eclipse.terminal.local.core.connector";
public static final String ENCODING = "UTF-8";
@@ -46,11 +48,11 @@
public static ITerminalConnector createLocalTerminalConnector() {
TerminalConnector.Factory factory = new TerminalConnector.Factory(){
- @Override public TerminalConnectorImpl makeConnector() {
+ @Override public TerminalConnectorDelegate makeConnector() {
return new LocalTerminalConnector();
}
};
- TerminalConnector connector = new TerminalConnector(factory, ID, localTerminalName, false);
+ TerminalConnector connector = new TerminalConnector(factory, ID, localTerminalName);
String errorMessage = connector.getInitializationErrorMessage();
if (errorMessage != null) {
throw new IllegalStateException(errorMessage);
@@ -63,7 +65,7 @@
/**
* Verifies that PTY support is available on this platform.
* @throws CoreException if PTY support is <strong>not</strong> available on this platform.
- * @see TerminalConnectorImpl#initialize()
+ * @see TerminalConnectorDelegate#initialize()
*/
@Override public void initialize() throws CoreException {
if (!isPlatformSupported()) {
@@ -72,9 +74,8 @@
}
}
- @Override public void connect(ITerminalControl control) {
- super.connect(control);
- control.setState(CONNECTING);
+ @Override protected void connect() {
+ terminalControl.setState(CONNECTING);
File workingDirectory = workingDirectory();
pseudoTerminal = new PseudoTerminal(workingDirectory);
pseudoTerminal.addLifeCycleListener(this);
@@ -82,15 +83,15 @@
pseudoTerminal.launch();
streamsProxy = new StreamsProxy(pseudoTerminal.systemProcess(), ENCODING);
terminalToRemoteStream = new BufferedOutputStream(new TerminalOutputStream(streamsProxy, ENCODING), 1024);
- addListeners(control, streamsProxy.getOutputStreamMonitor(), streamsProxy.getErrorStreamMonitor());
+ addListeners(terminalControl, streamsProxy.getOutputStreamMonitor(), streamsProxy.getErrorStreamMonitor());
if (streamsProxy != null) {
- control.setState(CONNECTED);
+ terminalControl.setState(CONNECTED);
return;
}
} catch (Throwable t) {
log(new Status(INFO, PLUGIN_ID, OK, "Unable to start terminal", t));
}
- control.setState(CLOSED);
+ terminalControl.setState(CLOSED);
}
private File workingDirectory() {
@@ -113,7 +114,6 @@
listener.streamAppended(monitor.getContents(), monitor);
}
- /** {@inheritDoc} */
@Override public OutputStream getTerminalToRemoteStream() {
return terminalToRemoteStream;
}
@@ -141,12 +141,12 @@
this.workingDirectory = workingDirectory;
}
- @Override protected void doDisconnect() {
+ @Override protected void onDisconnect() {
pseudoTerminal.disconnect();
}
@Override public void executionFinished() {
- fControl.setState(CLOSED);
+ terminalControl.setState(CLOSED);
if (streamsProxy != null) {
streamsProxy.close();
}
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/PseudoTerminal.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/PseudoTerminal.java
index 49278df..9620626 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/PseudoTerminal.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/PseudoTerminal.java
@@ -8,10 +8,11 @@
*/
package com.google.eclipse.terminal.local.core.connector;
-import static com.google.eclipse.terminal.local.util.Platform.*;
import static java.lang.Thread.currentThread;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static com.google.eclipse.terminal.local.util.Platform.*;
+
import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/TerminalOutputListener.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/TerminalOutputListener.java
index 42f23f9..d993d89 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/TerminalOutputListener.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/core/connector/TerminalOutputListener.java
@@ -14,7 +14,8 @@
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IStreamMonitor;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
+
+import com.google.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
/**
* @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferencePage.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferencePage.java
index 05c48af..766819a 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferencePage.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferencePage.java
@@ -8,15 +8,16 @@
*/
package com.google.eclipse.terminal.local.ui.preferences;
-import static com.google.eclipse.terminal.local.Activator.*;
-import static com.google.eclipse.terminal.local.ui.preferences.Messages.*;
-import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
import static org.eclipse.jface.layout.GridDataFactory.fillDefaults;
import static org.eclipse.jface.preference.ColorSelector.PROP_COLORCHANGE;
import static org.eclipse.jface.preference.PreferenceConverter.*;
import static org.eclipse.jface.resource.JFaceResources.TEXT_FONT;
import static org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn;
+import static com.google.eclipse.terminal.local.Activator.*;
+import static com.google.eclipse.terminal.local.ui.preferences.Messages.*;
+import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
+
import java.io.InputStream;
import java.util.Scanner;
@@ -121,7 +122,7 @@
lblFontData = new Label(grpFont, SWT.NONE);
gridDataFactory.span(1, 1).applyTo(lblFontData);
- lblFontData.setText(""); //$NON-NLS-1$
+ lblFontData.setText("");
btnChangeFont = new Button(grpFont, SWT.NONE);
btnChangeFont.setText(change);
@@ -141,7 +142,7 @@
previewer = new ProjectionViewer(contents, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL);
previewer.setEditable(false);
- previewer.setDocument(new Document(loadContentsFrom("ColorSettingPreviewText.txt"))); //$NON-NLS-1$
+ previewer.setDocument(new Document(loadContentsFrom("ColorSettingPreviewText.txt")));
StyledText previewerText = previewer.getTextWidget();
gridDataFactory.align(SWT.FILL, SWT.FILL).grab(true, true);
@@ -181,7 +182,7 @@
}
private String loadContentsFrom(String fileName) {
- String lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
+ String lineSeparator = System.getProperty("line.separator");
StringBuilder buffer = new StringBuilder();
Scanner scanner = null;
try {
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferences.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferences.java
index 866fe1e..0942ce9 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferences.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsAndFontsPreferences.java
@@ -8,9 +8,10 @@
*/
package com.google.eclipse.terminal.local.ui.preferences;
+import static org.eclipse.jface.preference.PreferenceConverter.*;
+
import static com.google.eclipse.terminal.local.Activator.preferenceStore;
import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
-import static org.eclipse.jface.preference.PreferenceConverter.*;
import org.eclipse.swt.graphics.*;
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/PopupMenu.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/PopupMenu.java
index e998958..53c2e03 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/PopupMenu.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/PopupMenu.java
@@ -13,10 +13,11 @@
import org.eclipse.jface.action.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
-import org.eclipse.tm.internal.terminal.control.actions.*;
-import org.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
import org.eclipse.ui.*;
+import com.google.eclipse.tm.internal.terminal.control.actions.*;
+import com.google.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
+
/**
* @author alruiz@google.com (Alex Ruiz)
*/
@@ -26,6 +27,7 @@
private final AbstractTerminalAction selectAll;
private final AbstractTerminalAction clearAll;
+ @SuppressWarnings("deprecation")
PopupMenu(IViewSite viewSite, VT100TerminalControl terminalControl) {
PopupMenuManager menuManager = new PopupMenuManager();
copy = menuManager.add(new TerminalActionCopy(terminalControl));
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java
index 7deb6d3..2bfac69 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java
@@ -8,17 +8,18 @@
*/
package com.google.eclipse.terminal.local.ui.view;
+import static org.eclipse.core.runtime.Path.fromOSString;
+import static org.eclipse.core.runtime.Status.OK_STATUS;
+import static org.eclipse.jface.resource.JFaceResources.TEXT_FONT;
+import static org.eclipse.jface.window.Window.OK;
+import static org.eclipse.ui.IWorkbenchPage.VIEW_ACTIVATE;
+
import static com.google.eclipse.terminal.local.Activator.*;
import static com.google.eclipse.terminal.local.ImageKeys.*;
import static com.google.eclipse.terminal.local.ui.preferences.ColorsAndFontsPreferences.*;
import static com.google.eclipse.terminal.local.ui.preferences.GeneralPreferences.*;
import static com.google.eclipse.terminal.local.ui.view.Messages.*;
import static com.google.eclipse.terminal.local.util.Platform.userHomeDirectory;
-import static org.eclipse.core.runtime.Path.fromOSString;
-import static org.eclipse.core.runtime.Status.OK_STATUS;
-import static org.eclipse.jface.resource.JFaceResources.TEXT_FONT;
-import static org.eclipse.jface.window.Window.OK;
-import static org.eclipse.ui.IWorkbenchPage.VIEW_ACTIVATE;
import java.util.UUID;
@@ -29,8 +30,6 @@
import org.eclipse.jface.util.*;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.*;
-import org.eclipse.tm.internal.terminal.control.ITerminalListener;
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
import org.eclipse.ui.*;
import org.eclipse.ui.contexts.*;
import org.eclipse.ui.part.ViewPart;
@@ -38,6 +37,8 @@
import com.google.eclipse.terminal.local.core.connector.LifeCycleListener;
import com.google.eclipse.terminal.local.ui.preferences.AbstractPreferencesChangeListener;
+import com.google.eclipse.tm.internal.terminal.control.ITerminalListener;
+import com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState;
/**
* @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java
index ca77647..1bb106d 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java
@@ -8,8 +8,9 @@
*/
package com.google.eclipse.terminal.local.ui.view;
+
import static com.google.eclipse.terminal.local.core.connector.LocalTerminalConnector.createLocalTerminalConnector;
-import static org.eclipse.tm.internal.terminal.provisional.api.TerminalState.CONNECTING;
+import static com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState.CONNECTING;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.layout.*;
@@ -17,12 +18,12 @@
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
-import org.eclipse.tm.internal.terminal.control.ITerminalListener;
-import org.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
-import org.eclipse.tm.internal.terminal.provisional.api.*;
import org.eclipse.ui.IViewSite;
import com.google.eclipse.terminal.local.core.connector.*;
+import com.google.eclipse.tm.internal.terminal.control.ITerminalListener;
+import com.google.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
/**
* @author alruiz@google.com (Alex Ruiz)
@@ -121,11 +122,11 @@
}
boolean isScrollLockEnabled() {
- return terminalControl.isScrollLock();
+ return terminalControl.isScrollLockOn();
}
void enableScrollLock(boolean enabled) {
- terminalControl.setScrollLock(enabled);
+ terminalControl.setScrollLockOn(enabled);
}
private static class TerminalListener implements ITerminalListener {
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/WarnOnCloseDialog.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/WarnOnCloseDialog.java
index e6261b7..5ac9d11 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/WarnOnCloseDialog.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/WarnOnCloseDialog.java
@@ -8,9 +8,10 @@
*/
package com.google.eclipse.terminal.local.ui.view;
+import static org.eclipse.jface.dialogs.IDialogConstants.*;
+
import static com.google.eclipse.terminal.local.ui.preferences.GeneralPreferences.warnOnClose;
import static com.google.eclipse.terminal.local.ui.view.Messages.*;
-import static org.eclipse.jface.dialogs.IDialogConstants.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/util/Platform.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/util/Platform.java
index 8d16ce1..4463895 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/util/Platform.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/util/Platform.java
@@ -9,6 +9,7 @@
package com.google.eclipse.terminal.local.util;
import static java.util.Collections.singletonMap;
+
import static org.eclipse.core.runtime.Platform.*;
import java.io.File;
diff --git a/com.google.eclipse.tm.terminal/.project b/com.google.eclipse.tm.terminal/.project
index 70bc0e6..d8cdded 100644
--- a/com.google.eclipse.tm.terminal/.project
+++ b/com.google.eclipse.tm.terminal/.project
@@ -20,15 +20,9 @@
<arguments>
</arguments>
</buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
- <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
</natures>
</projectDescription>
diff --git a/com.google.eclipse.tm.terminal/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.tm.terminal/.settings/org.eclipse.jdt.core.prefs
index c2dc3aa..468cbfa 100644
--- a/com.google.eclipse.tm.terminal/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.tm.terminal/.settings/org.eclipse.jdt.core.prefs
@@ -1,38 +1,10 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
-org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
@@ -40,35 +12,3 @@
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF b/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF
index b2cd922..7f47e81 100644
--- a/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.tm.terminal/META-INF/MANIFEST.MF
@@ -2,8 +2,8 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: com.google.eclipse.tm.terminal;singleton:=true
-Bundle-Version: 3.1.1.qualifier
-Bundle-Activator: org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin
+Bundle-Version: 1.1.0.qualifier
+Bundle-Activator: com.google.eclipse.tm.internal.terminal.control.impl.TerminalPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,
@@ -13,9 +13,9 @@
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ClassPath: .
-Export-Package: org.eclipse.tm.internal.terminal.connector;x-friends:="com.google.eclipse.terminal.local",
- org.eclipse.tm.internal.terminal.control;x-friends:="com.google.eclipse.terminal.local",
- org.eclipse.tm.internal.terminal.control.actions;x-friends:="com.google.eclipse.terminal.local",
- org.eclipse.tm.internal.terminal.emulator;x-friends:="com.google.eclipse.terminal.local",
- org.eclipse.tm.internal.terminal.provisional.api;x-friends:="com.google.eclipse.terminal.local",
- org.eclipse.tm.internal.terminal.provisional.api.provider;x-friends:="com.google.eclipse.terminal.local"
+Export-Package: com.google.eclipse.tm.internal.terminal.connector;x-friends:="com.google.eclipse.terminal.local",
+ com.google.eclipse.tm.internal.terminal.control;x-friends:="com.google.eclipse.terminal.local",
+ com.google.eclipse.tm.internal.terminal.control.actions;x-friends:="com.google.eclipse.terminal.local",
+ com.google.eclipse.tm.internal.terminal.emulator;x-friends:="com.google.eclipse.terminal.local",
+ com.google.eclipse.tm.internal.terminal.provisional.api;x-friends:="com.google.eclipse.terminal.local",
+ com.google.eclipse.tm.internal.terminal.provisional.api.provider;x-friends:="com.google.eclipse.terminal.local"
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/connector/TerminalConnector.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/connector/TerminalConnector.java
new file mode 100644
index 0000000..e9ddae1
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/connector/TerminalConnector.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Scharf (Wind River) - initial API and implementation
+ * Michael Scharf (Wind River) - [200541] Extract from TerminalConnectorExtension.TerminalConnectorProxy
+ * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl
+ * Uwe Stieber (Wind River) - [282996] [terminal][api] Add "hidden" attribute to terminal connector extension point
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.connector;
+
+import static com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState.CLOSED;
+
+import java.io.OutputStream;
+
+import org.eclipse.core.runtime.*;
+
+import com.google.eclipse.tm.internal.terminal.control.impl.TerminalMessages;
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
+import com.google.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorDelegate;
+
+/**
+ * An {@link ITerminalConnector} instance, also known as terminal connection type, for maintaining a single terminal
+ * connection.
+ *
+ * It provides all terminal connector functions that can be provided by static markup without loading the actual
+ * implementation class. The actual {@link TerminalConnectorDelegate} implementation class is lazily loaded by the provided
+ * {@link TerminalConnector.Factory} interface when needed. class, and delegates to the actual implementation when
+ * needed. The following methods can be called without initializing the contributed implementation class:
+ * {@link #getId()}, {@link #getName()}, {@link #getSettingsSummary()}, {@link #setTerminalSize(int, int)},
+ * {@link #getAdapter(Class)}.
+ */
+public class TerminalConnector implements ITerminalConnector {
+ /**
+ * Creates an instance of TerminalConnectorImpl. This is used to lazily load classed defined in extensions.
+ */
+ public interface Factory {
+ TerminalConnectorDelegate makeConnector() throws Exception;
+ }
+
+ private final TerminalConnector.Factory terminalConnectorFactory;
+ private final String name;
+ private final String id;
+
+ private TerminalConnectorDelegate connector;
+
+ //If the initialization of the class specified in the extension fails, this variable contains the error.
+ private Exception initializationException;
+
+ /**
+ * Constructor for the terminal connector.
+ *
+ * @param terminalConnectorFactory Factory for lazily instantiating the TerminalConnectorImpl when needed.
+ * @param id terminal connector ID. The connector is publicly known under this ID.
+ * @param name translatable name to display the connector in the UI.
+ */
+ public TerminalConnector(TerminalConnector.Factory terminalConnectorFactory, String id, String name) {
+ this.terminalConnectorFactory = terminalConnectorFactory;
+ this.id = id;
+ this.name = name;
+ }
+
+ @Override public String getInitializationErrorMessage() {
+ getConnectorDelegate();
+ if (initializationException != null) {
+ return initializationException.getLocalizedMessage();
+ }
+ return null;
+ }
+
+ @Override public String getId() {
+ return id;
+ }
+
+ @Override public String getName() {
+ return name;
+ }
+
+ private TerminalConnectorDelegate getConnectorDelegate() {
+ if (!isInitialized()) {
+ initializeConnector();
+ }
+ return connector;
+ }
+
+ private void initializeConnector() {
+ try {
+ connector = terminalConnectorFactory.makeConnector();
+ connector.initialize();
+ } catch (Exception e) {
+ initializationException = e;
+ connector = new TerminalConnectorDelegate() {
+ @Override protected void connect() {
+ terminalControl.setState(CLOSED);
+ terminalControl.setErrorMessage(getInitializationErrorMessage());
+ }
+
+ @Override public OutputStream getTerminalToRemoteStream() {
+ return null;
+ }
+
+ @Override public String getSettingsSummary() {
+ return null;
+ }
+ };
+ Logger.logException(e);
+ }
+ }
+
+ @Override public boolean isInitialized() {
+ return connector != null || initializationException != null;
+ }
+
+ @Override public void connect(ITerminalControl control) {
+ getConnectorDelegate().connect(control);
+ }
+
+ @Override public void disconnect() {
+ getConnectorDelegate().disconnect();
+ }
+
+ @Override public OutputStream getTerminalToRemoteStream() {
+ return getConnectorDelegate().getTerminalToRemoteStream();
+ }
+
+ @Override public String getSettingsSummary() {
+ if (connector != null) {
+ return getConnectorDelegate().getSettingsSummary();
+ }
+ return TerminalMessages.notInitialized;
+ }
+
+ @Override public boolean isLocalEcho() {
+ return getConnectorDelegate().isLocalEcho();
+ }
+
+ @Override public void setTerminalSize(int newWidth, int newHeight) {
+ // We assume that setTerminalSize is called also after the terminal has been initialized, otherwise we would have to
+ // cache the values.
+ if (connector != null) {
+ connector.setTerminalSize(newWidth, newHeight);
+ }
+ }
+
+ @Override public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ TerminalConnectorDelegate connector = null;
+ if (isInitialized()) {
+ connector = getConnectorDelegate();
+ }
+ // If we cannot create the connector then we cannot adapt.
+ if (connector != null) {
+ // Maybe the connector is adaptable.
+ if (connector instanceof IAdaptable) {
+ Object result = ((IAdaptable) connector).getAdapter(adapter);
+ // Not sure if the next block is needed.
+ if (result == null) {
+ // Defer to the platform.
+ result = Platform.getAdapterManager().getAdapter(connector, adapter);
+ }
+ if (result != null) {
+ return result;
+ }
+ }
+ // Maybe the real adapter is what we need.
+ if (adapter.isInstance(connector)) {
+ return connector;
+ }
+ }
+ // Maybe we have to be adapted.
+ return Platform.getAdapterManager().getAdapter(this, adapter);
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/connector/TerminalToRemoteInjectionOutputStream.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/connector/TerminalToRemoteInjectionOutputStream.java
new file mode 100644
index 0000000..54f1de2
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/connector/TerminalToRemoteInjectionOutputStream.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.connector;
+
+import java.io.*;
+
+class TerminalToRemoteInjectionOutputStream extends FilterOutputStream {
+ /**
+ * This class handles bytes written to the {@link TerminalToRemoteInjectionOutputStream}.
+ */
+ static public abstract class Interceptor {
+ protected OutputStream original;
+
+ public void begin(OutputStream original) throws IOException {
+ this.original = original;
+ }
+
+ public void write(int b) throws IOException {}
+
+ public void write(byte[] b, int off, int len) throws IOException {}
+
+ public void close() throws IOException {}
+
+ public void flush() {}
+ }
+
+ public static class BufferInterceptor extends Interceptor {
+ private final ByteArrayOutputStream fBuffer = new ByteArrayOutputStream();
+
+ @Override public void close() throws IOException {
+ original.write(fBuffer.toByteArray());
+ }
+
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ fBuffer.write(b, off, len);
+ }
+
+ @Override public void write(int b) throws IOException {
+ fBuffer.write(b);
+ }
+ }
+
+ private class TerminalFilterOutputStream extends OutputStream {
+ final private Object lock = TerminalToRemoteInjectionOutputStream.this;
+
+ @Override public void close() throws IOException {
+ synchronized (lock) {
+ if (injection == this) {
+ flush();
+ ungrabOutput();
+ }
+ }
+ }
+
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ synchronized (lock) {
+ checkStream();
+ out.write(b, off, len);
+ }
+ }
+
+ @Override public void write(byte[] b) throws IOException {
+ synchronized (lock) {
+ checkStream();
+ out.write(b);
+ }
+ }
+
+ @Override public void flush() throws IOException {
+ synchronized (lock) {
+ checkStream();
+ out.flush();
+ }
+ }
+
+ @Override public void write(int b) throws IOException {
+ synchronized (lock) {
+ checkStream();
+ out.write(b);
+ }
+ }
+
+ private void checkStream() throws IOException {
+ if (injection != this)
+ {
+ throw new IOException("Stream is closed");
+ }
+ }
+ }
+
+ private Interceptor interceptor;
+ private TerminalFilterOutputStream injection;
+
+ public TerminalToRemoteInjectionOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ synchronized protected void ungrabOutput() throws IOException {
+ if (interceptor != null) {
+ interceptor.close();
+ interceptor = null;
+ }
+ injection = null;
+ }
+
+ /**
+ * There can only be one injection stream active at a time. You must call close on the returned output stream to end
+ * the injection.
+ * @param interceptor This is used handle bytes sent while the injection stream is active.
+ * @return a output stream that can be used to write to the decorated stream.
+ * @throws IOException if something goes wrong.
+ */
+ public synchronized OutputStream grabOutput(Interceptor interceptor) throws IOException {
+ if (injection != null) {
+ throw new IOException("Buffer in use");
+ }
+ this.interceptor = interceptor;
+ this.interceptor.begin(out);
+ injection = new TerminalFilterOutputStream();
+ return injection;
+ }
+
+ public synchronized OutputStream grabOutput() throws IOException {
+ return grabOutput(new BufferInterceptor());
+ }
+
+ @Override synchronized public void close() throws IOException {
+ if (injection != null) {
+ injection.close();
+ }
+ super.close();
+ }
+
+ @Override synchronized public void flush() throws IOException {
+ if (interceptor != null) {
+ interceptor.flush();
+ }
+ out.flush();
+ }
+
+ @Override synchronized public void write(byte[] b, int off, int len) throws IOException {
+ if (interceptor != null) {
+ interceptor.write(b, off, len);
+ } else {
+ out.write(b, off, len);
+ }
+ }
+
+ @Override synchronized public void write(int b) throws IOException {
+ if (interceptor != null) {
+ interceptor.write(b);
+ } else {
+ out.write(b);
+ }
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/CommandInputFieldWithHistory.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/CommandInputFieldWithHistory.java
new file mode 100644
index 0000000..eec3746
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/CommandInputFieldWithHistory.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control;
+
+import static java.util.Arrays.asList;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.jface.fieldassist.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
+
+/**
+ * Manages the Command History for the command line input of the terminal control.
+ *
+ * <p>
+ * <ul>
+ * <li>Navigate with ARROW_UP,ARROW_DOWN,PAGE_UP,PAGE_DOWN</li>
+ * <li>ESC to cancel history editing</li>
+ * <li>History can be edited (by moving up and edit) but changes are not persistent (like in bash)</li>
+ * <li>If the same command is entered multiple times in a row, only one entry is kept in the history</li>
+ * </ul>
+ * </p>
+ */
+public class CommandInputFieldWithHistory implements ICommandInputField {
+ final List<String> allHistory = new ArrayList<String>();
+
+ // Keeps a modifiable history while in history editing mode.
+ List<String> editedHistory;
+
+ // The current position in the edit history.
+ private int editHistoryPosition = 0;
+
+ // The limit of the history.
+ private final int maxHistorySize;
+
+ private Text inputField;
+ private Sash sash;
+
+ public CommandInputFieldWithHistory(int maxHistorySize) {
+ this.maxHistorySize = maxHistorySize;
+ }
+
+ /**
+ * Add a line to the history.
+ * @param line The line to be added to the history.
+ */
+ protected void pushLine(String line) {
+ endHistoryMode();
+ // Anything to remember?
+ if (line == null || line.trim().length() == 0) {
+ return;
+ }
+ allHistory.add(0, line);
+ // Ignore if the same as last/
+ if (allHistory.size() > 1 && line.equals(allHistory.get(1))) {
+ allHistory.remove(0);
+ }
+ // Limit the history size.
+ if (allHistory.size() >= maxHistorySize) {
+ allHistory.remove(allHistory.size() - 1);
+ }
+ }
+
+ public void setHistory(String history) {
+ endHistoryMode();
+ allHistory.clear();
+ if (history == null) {
+ return;
+ }
+ allHistory.addAll(asList(history.split("\n")));
+ }
+
+ public String getHistory() {
+ StringBuilder buffer = new StringBuilder();
+ boolean separate = false;
+ for (String line : allHistory) {
+ if (line.length() > 0) {
+ if (separate) {
+ buffer.append("\n");
+ } else {
+ separate = true;
+ }
+ buffer.append(line);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Moves a line of text in history.
+ * @param lineToBeMoved the line of text to be moved.
+ * @param count (+1 or -1) for forward and backward movement (-1 goes back.)
+ * @return the new string to be displayed in the command line or {@code null}, if the limit is reached.
+ */
+ public String move(String lineToBeMoved, int count) {
+ if (!inHistoryMode()) {
+ editedHistory = new ArrayList<String>(allHistory.size() + 1);
+ editedHistory.add(lineToBeMoved);
+ editedHistory.addAll(allHistory);
+ editHistoryPosition = 0;
+ }
+ editedHistory.set(editHistoryPosition, lineToBeMoved);
+ if (editHistoryPosition + count >= editedHistory.size()) {
+ return null;
+ }
+ if (editHistoryPosition + count < 0) {
+ return null;
+ }
+ editHistoryPosition += count;
+ return editedHistory.get(editHistoryPosition);
+ }
+
+ private boolean inHistoryMode() {
+ return editedHistory != null;
+ }
+
+ /**
+ * Exit the history movements and go to position 0;
+ * @return the string to be shown in the command line
+ */
+ protected String escape() {
+ if (!inHistoryMode()) {
+ return null;
+ }
+ String line = editedHistory.get(0);
+ endHistoryMode();
+ return line;
+ }
+
+ private void endHistoryMode() {
+ editedHistory = null;
+ editHistoryPosition = 0;
+ }
+
+ @Override public void createControl(final Composite parent, final ITerminalViewControl terminal) {
+ sash = new Sash(parent, SWT.HORIZONTAL);
+ final GridData sashLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ sashLayoutData.heightHint = 5;
+ sash.setLayoutData(sashLayoutData);
+ sash.addListener(SWT.Selection, new Listener() {
+ @Override public void handleEvent(Event e) {
+ if (e.detail == SWT.DRAG) {
+ // Don't redraw during drag, it causes paint errors - bug 220971.
+ return;
+ }
+ // No idea why this is needed.
+ GridData inputFieldLayoutData = (GridData) inputField.getLayoutData();
+ Rectangle sashRect = sash.getBounds();
+ Rectangle containerRect = parent.getClientArea();
+
+ int h = inputField.getLineHeight();
+ // Make sure the input filed height is a multiple of the line height.
+ inputFieldLayoutData.heightHint = Math.max(((containerRect.height - e.y - sashRect.height) / h) * h, h);
+ // Do not show less then one line.
+ e.y = Math.min(e.y, containerRect.height - h);
+ inputField.setLayoutData(inputFieldLayoutData);
+ parent.layout();
+ // else the content assist icon will be replicated
+ parent.redraw();
+ }
+ });
+ inputField = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL);
+ GridData inputFieldLayoutData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ boolean installDecoration = true;
+ if (installDecoration) {
+ // The ContentAssistCommandAdapter says: "The client is responsible for ensuring that adequate space is reserved
+ // for the decoration."
+ // TODO: What is the "adequate space"?
+ inputFieldLayoutData.horizontalIndent = 6;
+ }
+ inputField.setLayoutData(inputFieldLayoutData);
+ inputField.setFont(terminal.getFont());
+ // Register field assist *before* the key listener.
+ // Otherwise the ENTER key is sent *first* to the input field and then to the field assist pop-up.
+ // (https://bugs.eclipse.org/bugs/show_bug.cgi?id=211659)
+ new ContentAssistCommandAdapter(
+ inputField, new TextContentAdapter(), new FieldAssist(), null, null, installDecoration);
+ inputField.addKeyListener(new KeyListener() {
+ @Override public void keyPressed(KeyEvent e) {
+ // If the field assist has handled the key already then ignore it.
+ // (https://bugs.eclipse.org/bugs/show_bug.cgi?id=211659)
+ if (!e.doit) {
+ return;
+ }
+ if (e.keyCode == '\n' || e.keyCode == '\r') {
+ e.doit = false;
+ String line = inputField.getText();
+ if (!terminal.pasteString(line + "\n")) {
+ return;
+ }
+ pushLine(line);
+ setCommand("");
+ }
+ if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.PAGE_UP) {
+ e.doit = false;
+ setCommand(move(inputField.getText(), 1));
+ }
+ if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.PAGE_DOWN) {
+ e.doit = false;
+ setCommand(move(inputField.getText(), -1));
+ }
+ if (e.keyCode == SWT.ESC) {
+ e.doit = false;
+ setCommand(escape());
+ }
+ }
+
+ private void setCommand(String line) {
+ if (line == null) {
+ return;
+ }
+ inputField.setText(line);
+ inputField.setSelection(inputField.getCharCount());
+ }
+
+ @Override public void keyReleased(KeyEvent e) {
+ }
+ });
+ }
+
+ @Override public void setFont(Font font) {
+ inputField.setFont(font);
+ inputField.getParent().layout(true);
+ }
+
+ @Override public void dispose() {
+ sash.dispose();
+ sash = null;
+ inputField.dispose();
+ inputField = null;
+ }
+
+ private class FieldAssist implements IContentProposalProvider {
+ @Override public IContentProposal[] getProposals(String contents, int position) {
+ String prefix = contents.substring(0, position);
+ List<IContentProposal> result = new ArrayList<IContentProposal>();
+ Collection<String> seen = new HashSet<String>();
+ for (String history : allHistory) {
+ if (history.startsWith(prefix) && !seen.contains(history)) {
+ // The content is the rest of the history item.
+ String content = history.substring(prefix.length());
+ result.add(new Proposal(content, history));
+ // Don't add this proposal again.
+ seen.add(history);
+ }
+ }
+ return result.toArray(new IContentProposal[result.size()]);
+ }
+ }
+
+ private static class Proposal implements IContentProposal {
+ private final String content;
+ private final String label;
+
+ Proposal(String content, String label) {
+ this.content = content;
+ this.label = label;
+ }
+
+ @Override public String getContent() {
+ return content;
+ }
+
+ @Override public int getCursorPosition() {
+ return content.length();
+ }
+
+ @Override public String getDescription() {
+ return null;
+ }
+
+ @Override public String getLabel() {
+ return label;
+ }
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ICommandInputField.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ICommandInputField.java
new file mode 100644
index 0000000..8b9dd2a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ICommandInputField.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control;
+
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Interface to create a command input control.
+ */
+public interface ICommandInputField {
+ void createControl(Composite parent, ITerminalViewControl terminal);
+
+ void dispose();
+
+ /**
+ * Sets the font of a control created with {@link #createControl(Composite, ITerminalViewControl)}.
+ * @param font the new text font.
+ */
+ void setFont(Font font);
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ITerminalListener.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ITerminalListener.java
new file mode 100644
index 0000000..b7817ca
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ITerminalListener.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control;
+
+import com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState;
+
+/**
+ * Provided by a view implementation.
+ */
+public interface ITerminalListener {
+ /**
+ * Called when the state of the connection has changed.
+ * @param state the state of the connection.
+ */
+ void setState(TerminalState state);
+
+ /**
+ * Set the title of the terminal.
+ * @param title the new title.
+ */
+ void setTerminalTitle(String title);
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ITerminalViewControl.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ITerminalViewControl.java
new file mode 100644
index 0000000..5f4f68f
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/ITerminalViewControl.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ ******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control;
+
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Control;
+
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
+
+public interface ITerminalViewControl {
+ void setEncoding(String encoding) throws UnsupportedEncodingException;
+
+ String getEncoding();
+
+ boolean isEmpty();
+
+ void setFont(Font font);
+
+ void setInvertedColors(boolean invert);
+
+ Font getFont();
+
+ Control getControl();
+
+ Control getRootControl();
+
+ boolean isDisposed();
+
+ void selectAll();
+
+ void clearTerminal();
+
+ void copy();
+
+ void paste();
+
+ String getSelection();
+
+ TerminalState getState();
+
+ Clipboard getClipboard();
+
+ void connectTerminal();
+
+ void disconnectTerminal();
+
+ void disposeTerminal();
+
+ boolean isConnected();
+
+ String getSettingsSummary();
+
+ boolean setFocus();
+
+ ITerminalConnector getTerminalConnector();
+
+ void setConnector(ITerminalConnector connector);
+
+ ITerminalConnector[] getConnectors();
+
+ void sendKey(char arg0);
+
+ public boolean pasteString(String string);
+
+ void setCommandInputField(ICommandInputField inputField);
+
+ ICommandInputField getCommandInputField();
+
+ public int getBufferLineLimit();
+
+ public void setBufferLineLimit(int bufferLineLimit);
+
+ boolean isScrollLockOn();
+
+ void setScrollLockOn(boolean on);
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/AbstractTerminalAction.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/AbstractTerminalAction.java
new file mode 100644
index 0000000..289b768
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/AbstractTerminalAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.*;
+
+import com.google.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+import com.google.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
+
+public abstract class AbstractTerminalAction extends Action {
+ private final ITerminalViewControl target;
+
+ public AbstractTerminalAction(String id) {
+ this(null, id, 0);
+ }
+
+ public AbstractTerminalAction(ITerminalViewControl target, String id) {
+ this(target, id, 0);
+ }
+
+ public AbstractTerminalAction(ITerminalViewControl target, String id, int style) {
+ super("", style);
+ this.target = target;
+ setId(id);
+ }
+
+ @Override public abstract void run();
+
+ protected void setUpAction(
+ String text, String toolTip, String image, String enabledImage, String disabledImage, boolean enabled) {
+ setUpAction(
+ text, toolTip, image, enabledImage, disabledImage, enabled, TerminalPlugin.getDefault().getImageRegistry());
+ }
+
+ protected void setUpAction(
+ String text, String toolTip, String hoverImage, String enabledImage, String disabledImage, boolean enabled,
+ ImageRegistry imageRegistry) {
+ setUpAction(
+ text, toolTip, imageRegistry.getDescriptor(hoverImage), imageRegistry.getDescriptor(enabledImage),
+ imageRegistry.getDescriptor(disabledImage), enabled);
+ }
+
+ protected void setUpAction(
+ String text, String toolTip, ImageDescriptor hoverImage, ImageDescriptor enabledImage,
+ ImageDescriptor disabledImage, boolean enabled) {
+ setText(text);
+ setToolTipText(toolTip);
+ setEnabled(enabled);
+ if (enabledImage != null) {
+ setImageDescriptor(enabledImage);
+ }
+ if (disabledImage != null) {
+ setDisabledImageDescriptor(disabledImage);
+ }
+ if (hoverImage != null) {
+ setHoverImageDescriptor(hoverImage);
+ }
+ }
+
+ /**
+ * Returns the terminal instance on which the action should operate.
+ *
+ * @return the terminal instance on which the action should operate.
+ */
+ protected ITerminalViewControl getTarget() {
+ return target;
+ }
+
+ /**
+ * Subclasses can update their action.
+ *
+ * @param aboutToShow {@code true} before the menu is shown, {@code false} when the menu gets hidden.
+ */
+ public void updateAction(boolean aboutToShow) {}
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/ActionMessages.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/ActionMessages.java
new file mode 100644
index 0000000..066af2b
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/ActionMessages.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import org.eclipse.osgi.util.NLS;
+
+public class ActionMessages extends NLS {
+ public static String copy;
+ public static String cut;
+ public static String paste;
+ public static String selectAll;
+ public static String clearAll;
+
+ static {
+ Class<?> clazz = ActionMessages.class;
+ NLS.initializeMessages(clazz.getName(), clazz);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/ActionMessages.properties b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/ActionMessages.properties
new file mode 100644
index 0000000..881315b
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/ActionMessages.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2003, 2009 Wind River Systems, Inc. and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+# NLS_MESSAGEFORMAT_NONE
+
+copy = Copy
+cut = Cut
+paste = Paste
+selectAll = Select All
+clearAll = Clear Terminal
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/Images.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/Images.java
new file mode 100644
index 0000000..68c1b8e
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/Images.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+public interface Images {
+ String IMAGE_DIR_ROOT = "icons/";
+ String IMAGE_DIR_LOCALTOOL = IMAGE_DIR_ROOT + "clcl16/";
+ String IMAGE_DIR_DLCL = IMAGE_DIR_ROOT + "dlcl16/";
+ String IMAGE_DIR_ELCL = IMAGE_DIR_ROOT + "elcl16/";
+ String IMAGE_CLCL_CLEAR_ALL = "ImageClclClearAll";
+ String IMAGE_DLCL_CLEAR_ALL = "ImageDlclClearAll";
+ String IMAGE_ELCL_CLEAR_ALL = "ImageElclClearAll";
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionClearAll.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionClearAll.java
new file mode 100644
index 0000000..652b5c4
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionClearAll.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ ********************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import static com.google.eclipse.tm.internal.terminal.control.actions.ActionMessages.clearAll;
+import static com.google.eclipse.tm.internal.terminal.control.actions.Images.*;
+
+import com.google.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+
+public class TerminalActionClearAll extends AbstractTerminalAction {
+ public TerminalActionClearAll() {
+ super(TerminalActionClearAll.class.getName());
+ setupAction();
+ }
+
+ public TerminalActionClearAll(ITerminalViewControl target) {
+ super(target, TerminalActionClearAll.class.getName());
+ setupAction();
+ }
+
+ private void setupAction() {
+ setUpAction(clearAll, clearAll, IMAGE_CLCL_CLEAR_ALL, IMAGE_ELCL_CLEAR_ALL, IMAGE_DLCL_CLEAR_ALL, false);
+ }
+
+ @Override public void run() {
+ ITerminalViewControl target = getTarget();
+ if (target != null) {
+ target.clearTerminal();
+ }
+ }
+
+ @Override public void updateAction(boolean aboutToShow) {
+ ITerminalViewControl target = getTarget();
+ setEnabled(target != null && !target.isEmpty());
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionCopy.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionCopy.java
new file mode 100644
index 0000000..575487e
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionCopy.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import static org.eclipse.ui.ISharedImages.*;
+
+import static com.google.eclipse.tm.internal.terminal.control.actions.ActionMessages.copy;
+
+import org.eclipse.ui.*;
+
+import com.google.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+
+public class TerminalActionCopy extends AbstractTerminalAction {
+ public TerminalActionCopy() {
+ super(TerminalActionCopy.class.getName());
+ setUpAction();
+ }
+
+ public TerminalActionCopy(ITerminalViewControl target) {
+ super(target, TerminalActionCopy.class.getName());
+ setUpAction();
+ }
+
+ private void setUpAction() {
+ ISharedImages shared = PlatformUI.getWorkbench().getSharedImages();
+ setUpAction(
+ copy, copy, shared.getImageDescriptor(IMG_TOOL_COPY), shared.getImageDescriptor(IMG_TOOL_COPY),
+ shared.getImageDescriptor(IMG_TOOL_COPY_DISABLED), true);
+ }
+
+ @Override public void run() {
+ ITerminalViewControl target = getTarget();
+ if (target != null) {
+ String selection = target.getSelection();
+ if (!selection.isEmpty()) {
+ target.copy();
+ } else {
+ target.sendKey('\u0003');
+ }
+ }
+ }
+
+ @Override public void updateAction(boolean aboutToShow) {
+ ITerminalViewControl target = getTarget();
+ boolean enabled = target != null;
+ if (aboutToShow && enabled) {
+ enabled = target.getSelection().length() > 0;
+ }
+ setEnabled(enabled);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionCut.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionCut.java
new file mode 100644
index 0000000..37ed070
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionCut.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import static org.eclipse.ui.ISharedImages.*;
+
+import static com.google.eclipse.tm.internal.terminal.control.actions.ActionMessages.cut;
+
+import org.eclipse.ui.*;
+
+import com.google.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+
+public class TerminalActionCut extends AbstractTerminalAction {
+ public TerminalActionCut() {
+ super(TerminalActionCut.class.getName());
+ setUpAction();
+ }
+
+ public TerminalActionCut(ITerminalViewControl target) {
+ super(target, TerminalActionCut.class.getName());
+ setUpAction();
+ }
+
+ private void setUpAction() {
+ ISharedImages shared = PlatformUI.getWorkbench().getSharedImages();
+ setUpAction(
+ cut, cut, shared.getImageDescriptor(IMG_TOOL_CUT), shared.getImageDescriptor(IMG_TOOL_CUT),
+ shared.getImageDescriptor(IMG_TOOL_CUT_DISABLED), true);
+ }
+
+ @Override public void run() {
+ ITerminalViewControl target = getTarget();
+ if (target != null) {
+ target.sendKey('\u0018');
+ }
+ }
+
+ @Override public void updateAction(boolean aboutToShow) {
+ // Cut is always disabled
+ setEnabled(false);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionPaste.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionPaste.java
new file mode 100644
index 0000000..057c79c
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionPaste.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Initial Contributors:
+ * The following Wind River employees contributed to the Terminal component
+ * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
+ * Helmut Haigermoser and Ted Williams.
+ *
+ * Contributors:
+ * Michael Scharf (Wind River) - split into core, view and connector plugins
+ * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
+ * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
+ * Uwe Stieber (Wind River) - [260372] [terminal] Certain terminal actions are enabled if no target terminal control is available
+ * Uwe Stieber (Wind River) - [294719] [terminal] SWT Widget disposed in TerminalActionPaste
+ * Martin Oberhuber (Wind River) - [296212] Cannot paste text into terminal on some Linux hosts
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import static org.eclipse.ui.ISharedImages.*;
+
+import static com.google.eclipse.tm.internal.terminal.control.actions.ActionMessages.paste;
+import static com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState.CONNECTED;
+
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.ui.*;
+
+import com.google.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+
+public class TerminalActionPaste extends AbstractTerminalAction {
+ public TerminalActionPaste() {
+ super(TerminalActionPaste.class.getName());
+ setUpAction();
+ }
+
+ public TerminalActionPaste(ITerminalViewControl target) {
+ super(target, TerminalActionPaste.class.getName());
+ setUpAction();
+ }
+
+ private void setUpAction() {
+ ISharedImages shared = PlatformUI.getWorkbench().getSharedImages();
+ setUpAction(
+ paste, paste, shared.getImageDescriptor(IMG_TOOL_PASTE), shared.getImageDescriptor(IMG_TOOL_PASTE_DISABLED),
+ shared.getImageDescriptor(IMG_TOOL_PASTE), false);
+ }
+
+ @Override public void run() {
+ ITerminalViewControl target = getTarget();
+ if (target != null) {
+ target.paste();
+ }
+ }
+
+ @Override public void updateAction(boolean aboutToShow) {
+ ITerminalViewControl target = getTarget();
+ boolean enabled = target != null && target.getClipboard() != null && !target.getClipboard().isDisposed();
+ if (enabled) {
+ String text = (String) target.getClipboard().getContents(TextTransfer.getInstance());
+ enabled = text != null && !text.isEmpty() && target.getState() == CONNECTED;
+ }
+ setEnabled(enabled);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionSelectAll.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionSelectAll.java
new file mode 100644
index 0000000..468eabe
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/actions/TerminalActionSelectAll.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.actions;
+
+import static com.google.eclipse.tm.internal.terminal.control.actions.ActionMessages.selectAll;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+
+import com.google.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+
+public class TerminalActionSelectAll extends AbstractTerminalAction {
+ public TerminalActionSelectAll() {
+ super(TerminalActionSelectAll.class.getName());
+ setUpAction();
+ }
+
+ public TerminalActionSelectAll(ITerminalViewControl target) {
+ super(target, TerminalActionSelectAll.class.getName());
+ setUpAction();
+ }
+
+ private void setUpAction() {
+ setUpAction(selectAll, selectAll, (ImageDescriptor) null, null, null, false);
+ }
+
+ @Override public void run() {
+ ITerminalViewControl target = getTarget();
+ if (target != null) {
+ target.selectAll();
+ }
+ }
+
+ @Override public void updateAction(boolean aboutToShow) {
+ ITerminalViewControl target = getTarget();
+ setEnabled(target != null && !target.isEmpty());
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java
new file mode 100644
index 0000000..53ede0a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.impl;
+
+import java.io.OutputStream;
+
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
+
+public interface ITerminalControlForText {
+
+ TerminalState getState();
+
+ void setState(TerminalState state);
+
+ void setTerminalTitle(String title);
+
+ ITerminalConnector getTerminalConnector();
+
+ OutputStream getOutputStream();
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalInputStream.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalInputStream.java
new file mode 100644
index 0000000..42765f2
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalInputStream.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 1996, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Scharf (Wind River)
+ * Douglas Lea (Addison Wesley) - [cq:1552] BoundedBufferWithStateTracking adapted to BoundedByteBuffer
+ *******************************************************************************/
+
+package com.google.eclipse.tm.internal.terminal.control.impl;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.swt.widgets.Display;
+
+import com.google.eclipse.tm.internal.terminal.util.BoundedByteBuffer;
+
+/**
+ * The main purpose of this class is to start a {@code Runnable} in the display thread when data is available and to
+ * pretend no data is available after a given amount of time the {@code Runnable} is running.
+ */
+public class TerminalInputStream extends InputStream {
+ // The maximum time in milliseconds the 'notifyChange' runs until 'ready()' returns false.
+ private final int uiTimeout;
+
+ // The output stream used by the terminal backend to write to the terminal.
+ protected final OutputStream outputStream;
+
+ // This runnable is called every time some characters are available from.
+ private final Runnable notifyChange;
+
+ // A shared timer for all terminals. This times is used to limit the time used in the display thread.
+ static Timer timer = new Timer(false);
+
+ // A blocking byte queue.
+ private final BoundedByteBuffer queue;
+
+ // The maximum amount of data read and written in one shot. The timer cannot interrupt reading this amount of data.
+ // This is used as optimization, because reading single characters can be very inefficient, because each call is
+ // synchronized.
+ // Block size must be smaller than the Queue capacity!
+ final int BLOCK_SIZE = 64;
+
+ // The runnable that is scheduled in the display tread. Takes care of the timeout management. It calls the
+ // 'notifyChange'.
+ // Synchronized with 'queue'.
+ private Runnable runnable;
+
+ // Used as flag to indicate that the current runnable has used enough time in the display thread. This variable is set
+ // by a timer thread after the Runnable starts to run in the Display thread after 'uiTimeout'.
+ // Synchronized with 'queue'.
+ private boolean enoughDisplayTime;
+
+ /**
+ * Constructor.
+ *
+ * @param bufferSize the size of the buffer of the output stream
+ * @param uiTimeout the maximum time the {@code notifyChange} {@code Runnable} runs. It will be rescheduled after
+ * {@code uiTimeout} if input data is still available.
+ * @param notifyChange a {@code Runnable} that is posted to the display thread via {@link Display#asyncExec}. The
+ * {@code Runnable} is posted several times!
+ */
+ public TerminalInputStream(int bufferSize, int uiTimeout, Runnable notifyChange) {
+ outputStream = new TerminalOutputStream();
+ this.notifyChange = notifyChange;
+ int capacity = bufferSize;
+ if (capacity < BLOCK_SIZE) {
+ capacity = 2 * BLOCK_SIZE;
+ }
+ queue = new BoundedByteBuffer(capacity);
+ this.uiTimeout = uiTimeout;
+ }
+
+ /**
+ * Posts the {@code Runnable} {@link #notifyChange} to the display thread, unless the {@code Runnable} is already
+ * scheduled. It will make {@link #ready} return {@code false} after {@link #uiTimeout} milliseconds.
+ */
+ void bytesAreAvailable() {
+ // synchronize on the queue to reduce the locks
+ synchronized (queue) {
+ if (runnable == null) {
+ runnable = new Runnable() {
+ @Override public void run() {
+ synchronized (queue) {
+ runnable = null;
+ }
+ startTimer(uiTimeout);
+ notifyChange.run();
+ }
+ };
+ // TODO: Make sure we don't create a display if the display is disposed.
+ Display.getDefault().asyncExec(runnable);
+ }
+ }
+ }
+
+ /**
+ * Starts a timer that sets {@link #enoughDisplayTime} to {@code true} after the given milliseconds.
+ *
+ * @param milliseconds the time after which {@code enoughDisplayTime} is set to {@code true}.
+ */
+ void startTimer(int milliseconds) {
+ synchronized (queue) {
+ enoughDisplayTime = false;
+ }
+ timer.schedule(new TimerTask() {
+ @Override public void run() {
+ synchronized (queue) {
+ enoughDisplayTime = true;
+ // there is some data available
+ if (queue.size() > 0) {
+ // schedule a new runnable to do the work
+ bytesAreAvailable();
+ }
+ }
+ }
+ }, milliseconds);
+ }
+
+ /**
+ * Returns the output stream used by the back-end to write to the terminal.
+ *
+ * @return the output stream used by the back-end to write to the terminal.
+ */
+ public OutputStream getOutputStream() {
+ return outputStream;
+ }
+
+ /**
+ * Indicate whether a character is available for the terminal to show. Must be called in the display thread.
+ * @return {@code true} if a character is available for the terminal to show, {@code false} otherwise.
+ */
+ @Override public int available() {
+ int available;
+ synchronized (queue) {
+ if (enoughDisplayTime) {
+ return 0;
+ }
+ available = queue.size();
+ }
+ // Limit the available amount of data. Otherwise our trick of limiting the time spend reading might not work.
+ if (available > BLOCK_SIZE) {
+ available = BLOCK_SIZE;
+ }
+ return available;
+ }
+
+ /**
+ * Returns the next available byte. Checks with {@link #available} if characters are available.
+ *
+ * @return the next available byte.
+ */
+ @Override public int read() throws IOException {
+ try {
+ return queue.read();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return -1;
+ }
+ }
+
+ /**
+ * Closing a {@code ByteArrayInputStream} has no effect. The methods in this class can be called after the stream has
+ * been closed without generating an {@code IOException}.
+ */
+ @Override public void close() {}
+
+ @Override public int read(byte[] b, int off, int len) throws IOException {
+ int n = 0;
+ // Read as much as we can using a single synchronized statement.
+ synchronized (queue) {
+ try {
+ // Make sure that not more than BLOCK_SIZE is read in one call.
+ while (queue.size() > 0 && n < len && n < BLOCK_SIZE) {
+ b[off + n] = queue.read();
+ n++;
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ return n;
+ }
+
+ /**
+ * An output stream that calls {@link TerminalInputStream#textAvailable} every time data is written to the stream. The
+ * data is written to {@link TerminalInputStream#queue}.
+ *
+ */
+ class TerminalOutputStream extends OutputStream {
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ try {
+ // optimization to avoid many synchronized sections: put the data in junks into the queue.
+ int newOff = off;
+ int end = off + len;
+ while (newOff < end) {
+ int n = newOff + BLOCK_SIZE;
+ if (n > end) {
+ n = end;
+ }
+ // now block the queue for the time we need to
+ // add some characters
+ synchronized (queue) {
+ for (int i = newOff; i < n; i++) {
+ queue.write(b[i]);
+ }
+ bytesAreAvailable();
+ }
+ newOff += BLOCK_SIZE;
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Override public void write(int b) throws IOException {
+ try {
+ // A kind of optimization, because both calls use the queue lock.
+ synchronized (queue) {
+ queue.write((byte) b);
+ bytesAreAvailable();
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalMessages.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalMessages.java
new file mode 100644
index 0000000..3856d90
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalMessages.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.impl;
+
+import org.eclipse.osgi.util.NLS;
+
+public class TerminalMessages extends NLS {
+ public static String terminalError;
+ public static String socketError;
+ public static String ioError;
+ public static String cannotConnectTo;
+ public static String notInitialized;
+
+ static {
+ Class<?> clazz = TerminalMessages.class;
+ NLS.initializeMessages(clazz.getName(), clazz);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalMessages.properties b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalMessages.properties
new file mode 100644
index 0000000..1fecdb3
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalMessages.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2003, 2009 Wind River Systems, Inc. and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+# NLS_MESSAGEFORMAT_VAR
+
+terminalError = Terminal Error
+socketError = Socket Error
+ioError = IO Error
+cannotConnectTo = Cannot initialize {0}:\n{1}
+notInitialized = Not Initialized
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
new file mode 100644
index 0000000..d1470ea
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.control.impl;
+
+import static org.eclipse.core.runtime.IStatus.ERROR;
+
+import static com.google.eclipse.tm.internal.terminal.control.actions.Images.*;
+
+import java.net.*;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.resource.*;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+public class TerminalPlugin extends AbstractUIPlugin {
+ public static final String PLUGIN_ID = "org.eclipse.tm.terminal";
+ public static final String HELP_VIEW = PLUGIN_ID + ".terminal_view";
+
+ protected static TerminalPlugin plugin;
+
+ public TerminalPlugin() {
+ plugin = this;
+ }
+
+ public static TerminalPlugin getDefault() {
+ return plugin;
+ }
+
+ public static boolean isOptionEnabled(String option) {
+ String enabled = Platform.getDebugOption(option);
+ if (enabled == null) {
+ return false;
+ }
+ return Boolean.parseBoolean(enabled);
+ }
+
+ @Override protected void initializeImageRegistry(ImageRegistry imageRegistry) {
+ try {
+ // Local tool-bars
+ putImageInRegistry(imageRegistry, IMAGE_CLCL_CLEAR_ALL, IMAGE_DIR_LOCALTOOL + "clear_co.gif");
+ // Enabled local tool-bars
+ putImageInRegistry(imageRegistry, IMAGE_ELCL_CLEAR_ALL, IMAGE_DIR_ELCL + "clear_co.gif");
+ // Disabled local tool-bars
+ putImageInRegistry(imageRegistry, IMAGE_DLCL_CLEAR_ALL, IMAGE_DIR_DLCL + "clear_co.gif");
+ } catch (MalformedURLException malformedURLException) {
+ malformedURLException.printStackTrace();
+ }
+ }
+
+ protected void putImageInRegistry(
+ ImageRegistry imageRegistry, String strKey, String relativePath) throws MalformedURLException {
+ URL url = TerminalPlugin.getDefault().getBundle().getEntry(relativePath);
+ ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(url);
+ imageRegistry.put(strKey, imageDescriptor);
+ }
+
+ public static void log(String message, Exception error) {
+ getDefault().getLog().log(new Status(ERROR, PLUGIN_ID, message, error));
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/EditActionAccelerators.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/EditActionAccelerators.java
similarity index 94%
rename from com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/EditActionAccelerators.java
rename to com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/EditActionAccelerators.java
index 6da42b1..7567292 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/EditActionAccelerators.java
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/EditActionAccelerators.java
@@ -6,7 +6,7 @@
*
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.tm.internal.terminal.emulator;
+package com.google.eclipse.tm.internal.terminal.emulator;
import static org.eclipse.jface.bindings.keys.SWTKeySupport.convertKeyStrokeToAccelerator;
@@ -21,8 +21,8 @@
* @author alruiz@google.com (Alex Ruiz)
*/
class EditActionAccelerators {
- private static final String COPY_COMMAND_ID = "com.google.eclipse.terminal.local.copy"; //$NON-NLS-1$
- private static final String PASTE_COMMAND_ID = "com.google.eclipse.terminal.local.paste"; //$NON-NLS-1$
+ private static final String COPY_COMMAND_ID = "com.google.eclipse.terminal.local.copy";
+ private static final String PASTE_COMMAND_ID = "com.google.eclipse.terminal.local.paste";
private final Map<Integer, String> commandIdsByAccelerator = new HashMap<Integer, String>();
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
new file mode 100644
index 0000000..07cfe95
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.emulator;
+
+import java.util.List;
+
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+
+import com.google.eclipse.tm.terminal.model.Style;
+
+public interface IVT100EmulatorBackend {
+ /**
+ * Erases all text from the terminal view. Including the history.
+ */
+ void clearAll();
+
+ /**
+ * Sets the dimensions of the addressable scroll space of the screen. Keeps the cursor position relative to the bottom
+ * of the screen.
+ *
+ * @param lines the number of lines.
+ * @param columns the number of columns.
+ */
+ void setDimensions(int lines, int columns);
+
+ /**
+ * Makes room for N characters on the current line at the cursor position. Text under the cursor moves right
+ * without wrapping at the end of the line.
+ *
+ * @param charactersToInsert the number of characters to insert.
+ */
+ void insertCharacters(int charactersToInsert);
+
+ /**
+ * Erases from the cursor position (inclusive) to the end of screen. The cursor does not move.
+ */
+ void eraseToEndOfScreen();
+
+ /**
+ * Erases from the beginning of screen to the cursor position (inclusive). The cursor does not move.
+ */
+ void eraseToCursor();
+
+ /**
+ * Erases the complete display. All lines are erased and changed to single-width. The cursor does not move.
+ */
+ void eraseAll();
+
+ /**
+ * Erases the complete line.
+ */
+ void eraseLine();
+
+ /**
+ * Erases from the cursor position (inclusive) to the end of line.
+ */
+ void eraseLineToEnd();
+
+ /**
+ * Erases from beginning of line to the cursor position (inclusive).
+ */
+ void eraseLineToCursor();
+
+ /**
+ * Inserts n lines at line with cursor. Lines displayed below cursor are moved down. Lines moved past the bottom
+ * margin are lost. This sequence is ignored when cursor is outside scrolling region.
+ *
+ * @param lineCount the number of lines to insert.
+ */
+ void insertLines(int lineCount);
+
+ /**
+ * Deletes n characters, starting with the character at the cursor position. When a character is deleted, all
+ * characters to the right of cursor move left. This creates a space character at right margin. This character has
+ * same character attribute as the last character moved left.
+ *
+ * @param charCount the number of characters to delete.
+ */
+ void deleteCharacters(int charCount);
+
+ /**
+ * Deletes n lines, starting at line with cursor. As lines are deleted, the lines displayed below cursor move up.
+ * The lines added to bottom of screen have spaces with the same character attributes as the last line moved up.
+ * This sequence is ignored when cursor is outside scrolling region.
+ *
+ * @param lineCount the number of lines to delete.
+ */
+ void deleteLines(int lineCount);
+
+ Style getDefaultStyle();
+
+ void setDefaultStyle(Style defaultStyle);
+
+ Style getStyle();
+
+ /**
+ * Sets the style to use.
+ *
+ * @param style the new style.
+ */
+ void setStyle(Style style);
+
+ /**
+ * Displays a subset of the newly-received text in the terminal view, wrapping text at the right edge of the screen
+ * and overwriting text when the cursor is not at the very end of the screen's text.
+ *
+ * <p>
+ * There are never any ANSI control characters or escape sequences in the text being displayed by this method (this
+ * includes newlines, carriage returns, and tabs.)
+ * </p>
+ *
+ * @param buffer the text to append.
+ */
+ void appendString(String buffer);
+
+ /**
+ * Process a newline (Control-J) character. A newline (NL) character just moves the cursor to the same column on the
+ * next line, creating new lines when the cursor reaches the bottom edge of the terminal. This is counter-intuitive,
+ * especially to UNIX programmers who are taught that writing a single NL to a terminal is sufficient to move the
+ * cursor to the first column of the next line, as if a carriage return (CR) and a NL were written.
+ *
+ * <p>
+ * UNIX terminals typically display a NL character as a CR followed by a NL because the terminal device typically has
+ * the ONLCR attribute bit set (see the termios(4) man page for details), which causes the terminal device driver to
+ * translate NL to CR + NL on output. The terminal itself (i.e., a hardware terminal or a terminal emulator, like
+ * xterm or this code) _always_ interprets a CR to mean "move the cursor to the beginning of the current
+ * line" and a NL to mean "move the cursor to the same column on the next line".
+ * </p>
+ */
+ void processNewline();
+
+ /**
+ * Returns the relative line number of the line containing the cursor. The returned line number is relative to the
+ * top-most visible line, which has relative line number 0.
+ *
+ * @return the relative line number of the line containing the cursor.
+ */
+ int getCursorLine();
+
+ int getCursorColumn();
+
+ /**
+ * Moves the cursor to the specified line and column.
+ *
+ * @param targetLine is the line number of a screen line, so it has a minimum value of 0 (the topmost screen line) and
+ * a maximum value of heightInLines - 1 (the bottom-most screen line). A line does not have to contain any text to
+ * move the cursor to any column in that line.
+ * @param targetColumn the given column.
+ */
+ void setCursor(int targetLine, int targetColumn);
+
+ void setCursorColumn(int targetColumn);
+
+ void setCursorLine(int targetLine);
+
+ int getLines();
+
+ int getColumns();
+
+ List<IHyperlink> hyperlinksAt(int line);
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/LoggingOutputStream.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/LoggingOutputStream.java
new file mode 100644
index 0000000..7ac101a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/LoggingOutputStream.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.emulator;
+
+import java.io.*;
+
+import com.google.eclipse.tm.internal.terminal.provisional.api.Logger;
+
+public class LoggingOutputStream extends FilterOutputStream {
+ public LoggingOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ if (Logger.isLogEnabled()) {
+ Logger.log("Received " + len + " bytes: '" + Logger.encode(new String(b, 0, len)) + "'");
+ }
+ if ((off | len | (b.length - (len + off)) | (off + len)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ for (int i = 0; i < len; i++) {
+ super.write(b[off + i]);
+ }
+ }
+
+ @Override public void write(int b) throws IOException {
+ if (Logger.isLogEnabled()) {
+ Logger.log("Received " + 1 + " bytes: '" + Logger.encode(new String(new byte[] { (byte) b }, 0, 1)) + "'");
+ }
+ super.write(b);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
new file mode 100644
index 0000000..44ad103
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.emulator;
+
+import java.io.PrintStream;
+import java.util.List;
+
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+
+import com.google.eclipse.tm.terminal.model.Style;
+
+public class VT100BackendTraceDecorator implements IVT100EmulatorBackend {
+ final IVT100EmulatorBackend backend;
+ final PrintStream out;
+
+ public VT100BackendTraceDecorator(IVT100EmulatorBackend backend, PrintStream out) {
+ this.backend = backend;
+ this.out = out;
+ }
+
+ @Override public void appendString(String buffer) {
+ out.println("appendString(\"" + buffer + "\")");
+ backend.appendString(buffer);
+ }
+
+ @Override public void clearAll() {
+ out.println("clearAll()");
+ backend.clearAll();
+ }
+
+ @Override public void deleteCharacters(int n) {
+ out.println("deleteCharacters(" + n + ")");
+ backend.deleteCharacters(n);
+ }
+
+ @Override public void deleteLines(int n) {
+ out.println("deleteLines(" + n + ")");
+ backend.deleteLines(n);
+ }
+
+ @Override public void eraseAll() {
+ out.println("eraseAll()");
+ backend.eraseAll();
+ }
+
+ @Override public void eraseLine() {
+ out.println("eraseLine()");
+ backend.eraseLine();
+ }
+
+ @Override public void eraseLineToCursor() {
+ out.println("eraseLineToCursor()");
+ backend.eraseLineToCursor();
+ }
+
+ @Override public void eraseLineToEnd() {
+ out.println("eraseLineToEnd()");
+ backend.eraseLineToEnd();
+ }
+
+ @Override public void eraseToCursor() {
+ out.println("eraseToCursor()");
+ backend.eraseToCursor();
+ }
+
+ @Override public void eraseToEndOfScreen() {
+ out.println("eraseToEndOfScreen()");
+ backend.eraseToEndOfScreen();
+ }
+
+ @Override public int getColumns() {
+ return backend.getColumns();
+ }
+
+ @Override public int getCursorColumn() {
+ return backend.getCursorColumn();
+ }
+
+ @Override public int getCursorLine() {
+ return backend.getCursorLine();
+ }
+
+ @Override public Style getDefaultStyle() {
+ return backend.getDefaultStyle();
+ }
+
+ @Override public int getLines() {
+ return backend.getLines();
+ }
+
+ @Override public Style getStyle() {
+ return backend.getStyle();
+ }
+
+ @Override public void insertCharacters(int charactersToInsert) {
+ out.println("insertCharacters(" + charactersToInsert + ")");
+ backend.insertCharacters(charactersToInsert);
+ }
+
+ @Override public void insertLines(int n) {
+ out.println("insertLines(" + n + ")");
+ backend.insertLines(n);
+ }
+
+ @Override public void processNewline() {
+ out.println("processNewline()");
+ backend.processNewline();
+ }
+
+ @Override public void setCursor(int targetLine, int targetColumn) {
+ out.println("setCursor(" + targetLine + ", " + targetColumn + ")");
+ backend.setCursor(targetLine, targetColumn);
+ }
+
+ @Override public void setCursorColumn(int targetColumn) {
+ out.println("setCursorColumn(" + targetColumn + ")");
+ backend.setCursorColumn(targetColumn);
+ }
+
+ @Override public void setCursorLine(int targetLine) {
+ out.println("setCursorLine(" + targetLine + ")");
+ backend.setCursorLine(targetLine);
+ }
+
+ @Override public void setDefaultStyle(Style defaultStyle) {
+ out.println("setDefaultStyle(" + defaultStyle + ")");
+ backend.setDefaultStyle(defaultStyle);
+ }
+
+ @Override public void setDimensions(int lines, int cols) {
+ out.println("setDimensions(" + lines + "," + cols + ")");
+ backend.setDimensions(lines, cols);
+ }
+
+ @Override public void setStyle(Style style) {
+ out.println("setStyle(" + style + ")");
+ backend.setStyle(style);
+ }
+
+ @Override public List<IHyperlink> hyperlinksAt(int line) {
+ return backend.hyperlinksAt(line);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100Emulator.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
new file mode 100644
index 0000000..73e795e
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
@@ -0,0 +1,837 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.emulator;
+
+import java.io.*;
+import java.util.List;
+
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.swt.events.*;
+
+import com.google.eclipse.tm.internal.terminal.control.impl.*;
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
+import com.google.eclipse.tm.terminal.model.*;
+
+/**
+ * This class processes character data received from the remote host and displays it to the user using the Terminal
+ * view's StyledText widget. This class processes ANSI control characters, including NUL, backspace, carriage return,
+ * line-feed, and a subset of ANSI escape sequences sufficient to allow use of screen-oriented applications, such as vi,
+ * Emacs, and any GNU readline-enabled application (bash, bc, ncftp, etc.).
+ * <p>
+ */
+public class VT100Emulator implements ControlListener {
+ // This is a character processing state: Initial state.
+ private static final int ANSISTATE_INITIAL = 0;
+
+ // This is a character processing state: We've seen an escape character.
+ private static final int ANSISTATE_ESCAPE = 1;
+
+ // Character processing state: We've seen a '[' after an escape character. Expecting a parameter character or a
+ // command character next.
+ private static final int ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND = 2;
+
+ // Character processing state: We've seen a ']' after an escape character. We are now expecting an operating system
+ // command that reprograms an intelligent terminal.
+ private static final int ANSISTATE_EXPECTING_OS_COMMAND = 3;
+
+ /**
+ * This field holds the current state of the Finite Terminal State Automaton (FSA) that recognizes ANSI escape
+ * sequences.
+ *
+ * @see #processNewText()
+ */
+ private int ansiState = ANSISTATE_INITIAL;
+
+ // Holds a reference to the {@link TerminalControl} object that instantiates this class.
+ private final ITerminalControlForText terminal;
+
+ // Holds a reference to the StyledText widget that is used to display text to the user.
+ private final IVT100EmulatorBackend text;
+
+ // Holds the saved absolute line number of the cursor when processing the "ESC 7" and "ESC 8" command sequences.
+ private int savedCursorLine = 0;
+
+ // Holds the saved column number of the cursor when processing the "ESC 7" and "ESC 8" command sequences.
+ private int savedCursorColumn = 0;
+
+ // Holds an array of StringBuffer objects, each of which is one parameter from the current ANSI escape
+ // sequence. For example, when parsing the escape sequence "\e[20;10H", this array holds the strings "20" and "10".
+ private final StringBuffer[] parameters = new StringBuffer[16];
+
+ // Holds the OS-specific command found in an escape sequence of the form "\e]...\u0007".
+ private final StringBuffer ansiOsCommand = new StringBuffer(128);
+
+ // Holds the index of the next unused element of the array stored in field 'parameters'.
+ private int nextAnsiParameter = 0;
+
+ private int nextChar = -1;
+
+ private Reader reader;
+
+ private boolean crAfterNewLine;
+
+ /**
+ * The constructor.
+ */
+ public VT100Emulator(ITerminalTextData data, ITerminalControlForText terminal, Reader reader) {
+ super();
+ this.terminal = terminal;
+ for (int i = 0; i < parameters.length; ++i) {
+ parameters[i] = new StringBuffer();
+ }
+ setInputStreamReader(reader);
+ if (TerminalPlugin.isOptionEnabled("com.google.eclipse.tm.terminal/debug/log/VT100Backend")) {
+ text = new VT100BackendTraceDecorator(new VT100EmulatorBackend(data), System.out);
+ } else {
+ text = new VT100EmulatorBackend(data);
+ }
+ Style style = Style.getStyle("BLACK", "WHITE");
+ text.setDefaultStyle(style);
+ text.setStyle(style);
+ }
+
+ /**
+ * Set the reader that this terminal gets its input from.
+ *
+ * The reader can be changed while the Terminal is running, but a change of the reader likely loses some characters
+ * which have not yet been fully read. Changing the reader can be done in order to change the selected Encoding,
+ * though. This is typically done when the Terminal is constructed, i.e. before it really starts operation; or, when
+ * the user manually selects a different encoding and thus doesn't care about losing old characters.
+ *
+ * @param reader the new reader.
+ */
+ public void setInputStreamReader(Reader reader) {
+ this.reader = reader;
+ }
+
+ public void setDimensions(int lines, int cols) {
+ text.setDimensions(lines, cols);
+ ITerminalConnector telnetConnection = getConnector();
+ if (telnetConnection != null) {
+ telnetConnection.setTerminalSize(text.getColumns(), text.getLines());
+ }
+ }
+
+ public void dispose() {
+ }
+
+ @Override public void controlMoved(ControlEvent event) {
+ }
+
+ @Override public void controlResized(ControlEvent event) {
+ adjustTerminalDimensions();
+ }
+
+ public void clearTerminal() {
+ text.clearAll();
+ }
+
+ public void fontChanged() {
+ if (text != null) {
+ adjustTerminalDimensions();
+ }
+ }
+
+ public void processText() {
+ try {
+ // Find the width and height of the terminal, and resize it to display an integral number of lines and columns.
+ adjustTerminalDimensions();
+ // Restore the caret offset, process and display the new text, then save
+ // the caret offset. See the documentation for field caretOffset for
+ // details.
+ // ISSUE: Is this causing the scroll-to-bottom-on-output behavior?
+ try {
+ processNewText();
+ } catch (IOException e) {
+ Logger.logException(e);
+ }
+ } catch (RuntimeException e) {
+ Logger.logException(e);
+ }
+ }
+
+ /**
+ * This method scans the newly received text, processing ANSI control characters and escape sequences and displaying
+ * normal text.
+ *
+ * @throws IOException if something goes wrong.
+ */
+ private void processNewText() throws IOException {
+ // Scan the newly received text.
+ while (hasNextChar()) {
+ char character = getNextChar();
+ switch (ansiState) {
+ case ANSISTATE_INITIAL:
+ switch (character) {
+ case '\u0000':
+ break; // NUL character. Ignore it.
+ case '\u0007':
+ processBEL(); // BEL (Control-G)
+ break;
+ case '\b':
+ processBackspace(); // Backspace
+ break;
+ case '\t':
+ processTab(); // Tab.
+ break;
+ case '\n':
+ processNewline(); // Newline (Control-J)
+ if (crAfterNewLine) {
+ processCarriageReturn(); // Carriage Return (Control-M)
+ }
+ break;
+ case '\r':
+ processCarriageReturn(); // Carriage Return (Control-M)
+ break;
+ case '\u001b':
+ ansiState = ANSISTATE_ESCAPE; // Escape.
+ break;
+ default:
+ processNonControlCharacters(character);
+ break;
+ }
+ break;
+ case ANSISTATE_ESCAPE:
+ // We've seen an escape character. Here, we process the character immediately following the escape.
+ switch (character) {
+ case '[':
+ ansiState = ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND;
+ nextAnsiParameter = 0;
+ // Erase the parameter strings in preparation for optional parameter characters.
+ for (int i = 0; i < parameters.length; ++i) {
+ parameters[i].delete(0, parameters[i].length());
+ }
+ break;
+ case ']':
+ ansiState = ANSISTATE_EXPECTING_OS_COMMAND;
+ ansiOsCommand.delete(0, ansiOsCommand.length());
+ break;
+ case '7':
+ // Save cursor position and character attributes.
+ ansiState = ANSISTATE_INITIAL;
+ savedCursorLine = relativeCursorLine();
+ savedCursorColumn = getCursorColumn();
+ break;
+ case '8':
+ // Restore cursor and attributes to previously saved position.
+ ansiState = ANSISTATE_INITIAL;
+ moveCursor(savedCursorLine, savedCursorColumn);
+ break;
+ case 'c':
+ // Reset the terminal.
+ ansiState = ANSISTATE_INITIAL;
+ resetTerminal();
+ break;
+ default:
+ Logger.log("Unsupported escape sequence: escape '" + character + "'");
+ ansiState = ANSISTATE_INITIAL;
+ break;
+ }
+ break;
+ case ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND:
+ // Parameters can appear after the '[' in an escape sequence, but they are optional.
+ if (character == '@' || (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z')) {
+ ansiState = ANSISTATE_INITIAL;
+ processAnsiCommandCharacter(character);
+ } else {
+ processAnsiParameterCharacter(character);
+ }
+ break;
+ case ANSISTATE_EXPECTING_OS_COMMAND:
+ // A BEL (\u0007) character marks the end of the OSC sequence.
+ if (character == '\u0007') {
+ ansiState = ANSISTATE_INITIAL;
+ processAnsiOsCommand();
+ } else {
+ ansiOsCommand.append(character);
+ }
+ break;
+ default:
+ // This should never happen! If it does happen, it means there is a bug in the FSA. For robustness, we return to
+ // the initial state.
+ Logger.log("INVALID ANSI FSA STATE: " + ansiState);
+ ansiState = ANSISTATE_INITIAL;
+ break;
+ }
+ }
+ }
+
+ private void resetTerminal() {
+ text.eraseAll();
+ text.setCursor(0, 0);
+ text.setStyle(text.getDefaultStyle());
+ }
+
+ // This method is called when we have parsed an OS Command escape sequence. The only one we support is
+ // "\e]0;...\u0007", which sets the terminal title.
+ private void processAnsiOsCommand() {
+ if (ansiOsCommand.charAt(0) != '0' || ansiOsCommand.charAt(1) != ';') {
+ Logger.log("Ignoring unsupported ANSI OSC sequence: '" + ansiOsCommand + "'");
+ return;
+ }
+ terminal.setTerminalTitle(ansiOsCommand.substring(2));
+ }
+
+ // Dispatches control to various processing methods based on the command character found in the most recently received
+ // ANSI escape sequence. This method only handles command characters that follow the ANSI standard Control Sequence
+ // Introducer (CSI), which is "\e[...", where "..." is an optional ';'-separated sequence of numeric parameters.
+ private void processAnsiCommandCharacter(char ansiCommandCharacter) {
+ // If the width or height of the terminal is ridiculously small (one line or column or less), don't even try to
+ // process the escape sequence. This avoids throwing an exception (SPR 107450). The display will be messed up, but
+ // what did you user expect by making the terminal so small?
+ switch (ansiCommandCharacter) {
+ case '@':
+ // Insert character(s).
+ processAnsiCommand_atsign();
+ break;
+ case 'A':
+ // Move cursor up N lines (default 1).
+ processAnsiCommand_A();
+ break;
+ case 'B':
+ // Move cursor down N lines (default 1).
+ processAnsiCommand_B();
+ break;
+ case 'C':
+ // Move cursor forward N columns (default 1).
+ processAnsiCommand_C();
+ break;
+ case 'D':
+ // Move cursor backward N columns (default 1).
+ processAnsiCommand_D();
+ break;
+ case 'E':
+ // Move cursor to first column of Nth next line (default 1).
+ processAnsiCommand_E();
+ break;
+ case 'F':
+ // Move cursor to first column of Nth previous line (default 1).
+ processAnsiCommand_F();
+ break;
+ case 'G':
+ // Move to column N of current line (default 1).
+ processAnsiCommand_G();
+ break;
+ case 'H':
+ // Set cursor Position.
+ processAnsiCommand_H();
+ break;
+ case 'J':
+ // Erase part or all of display. Cursor does not move.
+ processAnsiCommand_J();
+ break;
+ case 'K':
+ // Erase in line (cursor does not move).
+ processAnsiCommand_K();
+ break;
+ case 'L':
+ // Insert line(s) (current line moves down).
+ processAnsiCommand_L();
+ break;
+ case 'M':
+ // Delete line(s).
+ processAnsiCommand_M();
+ break;
+ case 'm':
+ // Set Graphics Rendition (SGR).
+ processAnsiCommand_m();
+ break;
+ case 'n':
+ // Device Status Report (DSR).
+ processAnsiCommand_n();
+ break;
+ case 'P':
+ // Delete character(s).
+ processAnsiCommand_P();
+ break;
+ case 'S':
+ // Scroll up.
+ // Emacs, vi, and GNU readline don't seem to use this command, so we ignore it for now.
+ break;
+ case 'T':
+ // Scroll down.
+ // Emacs, vi, and GNU readline don't seem to use this command, so we ignore it for now.
+ break;
+ case 'X':
+ // Erase character.
+ // Emacs, vi, and GNU readline don't seem to use this command, so we ignore it for now.
+ break;
+ case 'Z':
+ // Cursor back tab.
+ // Emacs, vi, and GNU readline don't seem to use this command, so we ignore it for now.
+ break;
+
+ default:
+ Logger.log("Ignoring unsupported ANSI command character: '" + ansiCommandCharacter + "'");
+ break;
+ }
+ }
+
+ // Makes room for N characters on the current line at the cursor position. Text under the cursor moves right without
+ // wrapping at the end of the line.
+ private void processAnsiCommand_atsign() {
+ int charactersToInsert = getAnsiParameter(0);
+ text.insertCharacters(charactersToInsert);
+ }
+
+ // Moves the cursor up by the number of lines specified by the escape sequence parameter (default 1).
+ private void processAnsiCommand_A() {
+ moveCursorUp(getAnsiParameter(0));
+ }
+
+ // Moves the cursor down by the number of lines specified by the escape sequence parameter (default 1).
+ private void processAnsiCommand_B() {
+ moveCursorDown(getAnsiParameter(0));
+ }
+
+ // Moves the cursor forward by the number of columns specified by the escape sequence parameter (default 1).
+ private void processAnsiCommand_C() {
+ moveCursorForward(getAnsiParameter(0));
+ }
+
+ // Moves the cursor backward by the number of columns specified by the escape sequence parameter (default 1).
+ private void processAnsiCommand_D() {
+ moveCursorBackward(getAnsiParameter(0));
+ }
+
+ // Moves the cursor to the first column of the Nth next line, where N is specified by the ANSI parameter (default 1).
+ private void processAnsiCommand_E() {
+ int linesToMove = getAnsiParameter(0);
+ moveCursor(relativeCursorLine() + linesToMove, 0);
+ }
+
+ // Moves the cursor to the first column of the Nth previous line, where N is specified by the ANSI parameter
+ // (default 1).
+ private void processAnsiCommand_F() {
+ int linesToMove = getAnsiParameter(0);
+ moveCursor(relativeCursorLine() - linesToMove, 0);
+ }
+
+ // Moves the cursor within the current line to the column specified by the ANSI parameter (default is column 1).
+ private void processAnsiCommand_G() {
+ int targetColumn = 1;
+ if (parameters[0].length() > 0) {
+ targetColumn = getAnsiParameter(0) - 1;
+ }
+ moveCursor(relativeCursorLine(), targetColumn);
+ }
+
+ // Sets the cursor to a position specified by the escape sequence parameters (default is the upper left corner of the
+ // screen).
+ private void processAnsiCommand_H() {
+ moveCursor(getAnsiParameter(0) - 1, getAnsiParameter(1) - 1);
+ }
+
+ // Deletes some (or all) of the text on the screen without moving the cursor.
+ private void processAnsiCommand_J() {
+ int parameter;
+ if (parameters[0].length() == 0) {
+ parameter = 0;
+ } else {
+ parameter = getAnsiParameter(0);
+ }
+ switch (parameter) {
+ case 0:
+ text.eraseToEndOfScreen();
+ break;
+ case 1:
+ // Erase from beginning to current position (inclusive).
+ text.eraseToCursor();
+ break;
+ case 2:
+ // Erase entire display.
+ text.eraseAll();
+ break;
+ default:
+ Logger.log("Unexpected J-command parameter: " + parameter);
+ break;
+ }
+ }
+
+ // Deletes some (or all) of the text in the current line without moving the cursor.
+ private void processAnsiCommand_K() {
+ int parameter = getAnsiParameter(0);
+ switch (parameter) {
+ case 0:
+ // Erase from beginning to current position (inclusive).
+ text.eraseLineToCursor();
+ break;
+ case 1:
+ // Erase from current position to end (inclusive).
+ text.eraseLineToEnd();
+ break;
+ case 2:
+ // Erase entire line.
+ text.eraseLine();
+ break;
+ default:
+ Logger.log("Unexpected K-command parameter: " + parameter);
+ break;
+ }
+ }
+
+ // Inserts one or more blank lines. The current line of text moves down. Text that falls off the bottom of the screen
+ // is deleted.
+ private void processAnsiCommand_L() {
+ text.insertLines(getAnsiParameter(0));
+ }
+
+ // Deletes one or more lines of text. Any lines below the deleted lines move up, which we implement by appending
+ // new lines to the end of the text.
+ private void processAnsiCommand_M() {
+ text.deleteLines(getAnsiParameter(0));
+ }
+
+ // Sets a new graphics rendition mode, such as foreground/background color, bold/normal text, and reverse video.
+ private void processAnsiCommand_m() {
+ if (parameters[0].length() == 0) {
+ // This a special case: when no ANSI parameter is specified, act like a single parameter equal to 0 was specified.
+ parameters[0].append('0');
+ }
+ Style style = text.getStyle();
+ // There are a non-zero number of ANSI parameters. Process each one in order.
+ int parameterCount = parameters.length;
+ int parameterIndex = 0;
+ while (parameterIndex < parameterCount && parameters[parameterIndex].length() > 0) {
+ int parameter = getAnsiParameter(parameterIndex);
+ switch (parameter) {
+ case 0:
+ // Reset all graphics modes.
+ style = text.getDefaultStyle();
+ break;
+ case 1:
+ style = style.setBold(true);
+ break;
+ case 4:
+ style = style.setUnderline(true);
+ break;
+ case 5:
+ style = style.setBlink(true);
+ break;
+ case 7:
+ style = style.setReverse(true);
+ break;
+ case 10: // Set primary font. Ignored.
+ break;
+ case 21:
+ case 22:
+ style = style.setBold(false);
+ break;
+ case 24:
+ style = style.setUnderline(false);
+ break;
+ case 25:
+ style = style.setBlink(false);
+ break;
+ case 27:
+ style = style.setReverse(false);
+ break;
+ case 30:
+ style = style.setForground("BLACK");
+ break;
+ case 31:
+ style = style.setForground("RED");
+ break;
+ case 32:
+ style = style.setForground("GREEN");
+ break;
+ case 33:
+ style = style.setForground("YELLOW");
+ break;
+ case 34:
+ style = style.setForground("BLUE");
+ break;
+ case 35:
+ style = style.setForground("MAGENTA");
+ break;
+ case 36:
+ style = style.setForground("CYAN");
+ break;
+ case 37:
+ style = style.setForground("WHITE_FOREGROUND");
+ break;
+ case 40:
+ style = style.setBackground("BLACK");
+ break;
+ case 41:
+ style = style.setBackground("RED");
+ break;
+ case 42:
+ style = style.setBackground("GREEN");
+ break;
+ case 43:
+ style = style.setBackground("YELLOW");
+ break;
+ case 44:
+ style = style.setBackground("BLUE");
+ break;
+ case 45:
+ style = style.setBackground("MAGENTA");
+ break;
+ case 46:
+ style = style.setBackground("CYAN");
+ break;
+ case 47:
+ style = style.setBackground("WHITE");
+ break;
+ default:
+ Logger.log("Unsupported graphics rendition parameter: " + parameter);
+ break;
+ }
+ ++parameterIndex;
+ }
+ text.setStyle(style);
+ }
+
+ // Responds to an ANSI Device Status Report (DSR) command from the remote endpoint requesting the cursor position.
+ // Requests for other kinds of status are ignored.
+ private void processAnsiCommand_n() {
+ // Do nothing if the numeric parameter was not 6 (which means report cursor position).
+ if (getAnsiParameter(0) != 6) {
+ return;
+ }
+ // Send the ANSI cursor position (which is 1-based) to the remote endpoint.
+ String positionReport = "\u001b[" + (relativeCursorLine() + 1) + ";" + (getCursorColumn() + 1) + "R";
+ try {
+ // TODO(alruiz): use same encoding as terminal.
+ OutputStreamWriter streamWriter = new OutputStreamWriter(terminal.getOutputStream(), "ISO-8859-1");
+ streamWriter.write(positionReport, 0, positionReport.length());
+ streamWriter.flush();
+ } catch (IOException ex) {
+ Logger.log("Caught IOException!");
+ }
+ }
+
+ // Deletes one or more characters starting at the current cursor position. Characters on the same line and to the
+ // right of the deleted characters move left. If there are no characters on the current line at or to the right of the
+ // cursor column, no text is deleted.
+ private void processAnsiCommand_P() {
+ text.deleteCharacters(getAnsiParameter(0));
+ }
+
+ // Returns one of the numeric ANSI parameters received in the most recent escape sequence.
+ private int getAnsiParameter(int parameterIndex) {
+ if (parameterIndex < 0 || parameterIndex >= parameters.length) {
+ // This should never happen.
+ return -1;
+ }
+ String parameter = parameters[parameterIndex].toString();
+ if (parameter.length() == 0) {
+ return 1;
+ }
+ int parameterValue = 1;
+ // Don't trust the remote endpoint to send well formed numeric parameters.
+ try {
+ parameterValue = Integer.parseInt(parameter);
+ } catch (NumberFormatException ex) {
+ parameterValue = 1;
+ }
+ return parameterValue;
+ }
+
+ // Processes a single parameter character in an ANSI escape sequence. Parameters are the (optional) characters
+ // between the leading "\e[" and the command character in an escape sequence (e.g., in the escape sequence
+ // "\e[20;10H", the parameter characters are "20;10"). Parameters are integers separated by one or more ';'s.
+ private void processAnsiParameterCharacter(char ch) {
+ if (ch == ';') {
+ ++nextAnsiParameter;
+ } else {
+ if (nextAnsiParameter < parameters.length) {
+ parameters[nextAnsiParameter].append(ch);
+ }
+ }
+ }
+
+ // Processes a contiguous sequence of non-control characters. This is a performance optimization, so that we don't
+ // have to insert or append each non-control character individually to the StyledText widget. A non-control character
+ // is any character that passes the condition in the below while loop.
+ private void processNonControlCharacters(char character) throws IOException {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append(character);
+ // Identify a contiguous sequence of non-control characters, starting at firstNonControlCharacterIndex in newText.
+ while (hasNextChar()) {
+ character = getNextChar();
+ if (character == '\u0000' || character == '\b' || character == '\t' || character == '\u0007' || character == '\n'
+ || character == '\r' || character == '\u001b') {
+ pushBackChar(character);
+ break;
+ }
+ buffer.append(character);
+ }
+ // Now insert the sequence of non-control characters in the StyledText widget
+ // at the location of the cursor.
+ displayNewText(buffer.toString());
+ }
+
+ // Displays a subset of the newly-received text in the Terminal view, wrapping text at the right edge of the screen
+ // and overwriting text when the cursor is not at the very end of the screen's text.
+ // There are never any ANSI control characters or escape sequences in the text being displayed by this method (this
+ // includes newlines, carriage returns, and tabs).
+ private void displayNewText(String buffer) {
+ text.appendString(buffer);
+ }
+
+ // Processes a BEL (Control-G) character.
+ private void processBEL() {
+ // TODO
+ // Display.getDefault().beep();
+ }
+
+ // Processes a backspace (Control-H) character.
+ private void processBackspace() {
+ moveCursorBackward(1);
+ }
+
+ // Processes a tab (Control-I) character. We don't insert a tab character into the StyledText widget. Instead, we move
+ // the cursor forward to the next tab stop, without altering any of the text. Tab stops are every 8 columns. The
+ // cursor will never move past the rightmost column.
+ private void processTab() {
+ moveCursorForward(8 - (getCursorColumn() % 8));
+ }
+
+ // Processes a newline (Control-J) character. A newline (NL) character just moves the cursor to the same column on the
+ // next line, creating new lines when the cursor reaches the bottom edge of the terminal. This is counter-intuitive,
+ // especially to UNIX programmers who are taught that writing a single NL to a terminal is sufficient to move the
+ // cursor to the first column of the next line, as if a carriage return (CR) and a NL were written.
+ //
+ // UNIX terminals typically display a NL character as a CR followed by a NL because the terminal device typically has
+ // the ONLCR attribute bit set (see the termios(4) man page for details), which causes the terminal device driver to
+ // translate NL to CR + NL on output. The terminal itself (i.e., a hardware terminal or a terminal emulator, like
+ // xterm or this code) _always_ interprets a CR to mean "move the cursor to the beginning of the current
+ // line" and a NL to mean "move the cursor to the same column on the next line".
+ private void processNewline() {
+ text.processNewline();
+ }
+
+ // Processes a Carriage Return (Control-M).
+ private void processCarriageReturn() {
+ text.setCursorColumn(0);
+ }
+
+ // Computes the width of the terminal in columns and its height in lines, then adjusts the width and height of the
+ // view's StyledText widget so that it displays an integral number of lines and columns of text. The adjustment is
+ // always to shrink the widget vertically or horizontally, because if the control were to grow, it would be clipped by
+ // the edges of the view window (i.e., the view window does not become larger to accommodate its contents becoming
+ // larger).
+ //
+ // This method must be called immediately before each time text is written to the terminal so that we can properly
+ // line wrap text. Because it is called so frequently, it must be fast when there is no resizing to be done.
+ private void adjustTerminalDimensions() {
+ // Compute how many pixels we need to shrink the StyledText control vertically to make it display an integral number
+ // of lines of text.
+ //
+ // TODO
+ // if(text.getColumns()!=80 && text.getLines()!=80) text.setDimensions(24, 80);
+ ITerminalConnector connector = getConnector();
+ // TODO MSA: send only if dimensions have really changed!
+ if (connector != null) {
+ connector.setTerminalSize(text.getColumns(), text.getLines());
+ }
+ }
+
+ private ITerminalConnector getConnector() {
+ if (terminal.getTerminalConnector() != null) {
+ return terminal.getTerminalConnector();
+ }
+ return null;
+ }
+
+ // Returns the relative line number of the line containing the cursor. The returned line number is relative to the
+ // top-most visible line, which has relative line number 0.
+ private int relativeCursorLine() {
+ return text.getCursorLine();
+ }
+
+ // Moves the cursor to the specified line and column. Parameter <i>targetLine</i> is the line number of a screen line,
+ // so it has a minimum value of 0 (the topmost screen line) and a maximum value of heightInLines - 1 (the
+ // bottom-most screen line). A line does not have to contain any text to move the cursor to any column in that line.
+ private void moveCursor(int targetLine, int targetColumn) {
+ text.setCursor(targetLine, targetColumn);
+ }
+
+ // Moves the cursor down n lines, but won't move the cursor past the bottom of the screen. This method does not cause
+ // any scrolling.
+ private void moveCursorDown(int lines) {
+ moveCursor(relativeCursorLine() + lines, getCursorColumn());
+ }
+
+ // Moves the cursor up n lines, but won't move the cursor past the top of the screen. This method does not cause any
+ // scrolling.
+ private void moveCursorUp(int lines) {
+ moveCursor(relativeCursorLine() - lines, getCursorColumn());
+ }
+
+ // Method moves the cursor forward n columns, but won't move the cursor past the right edge of the screen, nor will
+ // it move the cursor onto the next line. This method does not cause any scrolling.
+ private void moveCursorForward(int columnsToMove) {
+ moveCursor(relativeCursorLine(), getCursorColumn() + columnsToMove);
+ }
+
+ // Moves the cursor backward n columns, but won't move the cursor past the left edge of the screen, nor will it move
+ // the cursor onto the previous line. This method does not cause any scrolling.
+ private void moveCursorBackward(int columnsToMove) {
+ moveCursor(relativeCursorLine(), getCursorColumn() - columnsToMove);
+ }
+
+ /**
+ * Resets the state of the terminal text (foreground color, background color, font style and other internal state). It
+ * essentially makes it ready for new input.
+ */
+ public void resetState() {
+ ansiState = ANSISTATE_INITIAL;
+ text.setStyle(text.getDefaultStyle());
+ }
+
+ private char getNextChar() throws IOException {
+ int c = -1;
+ if (nextChar != -1) {
+ c = nextChar;
+ nextChar = -1;
+ } else {
+ c = reader.read();
+ }
+ // TODO: better end of file handling
+ if (c == -1) {
+ c = 0;
+ }
+ return (char) c;
+ }
+
+ private boolean hasNextChar() throws IOException {
+ if (nextChar >= 0) {
+ return true;
+ }
+ return reader.ready();
+ }
+
+ /**
+ * Put back one character to the stream. This method can push back exactly one character. The character is the next
+ * character returned by {@link #getNextChar}.
+ *
+ * @param c the character to be pushed back.
+ */
+ private void pushBackChar(char c) {
+ nextChar = c;
+ }
+
+ private int getCursorColumn() {
+ return text.getCursorColumn();
+ }
+
+ public boolean isCrAfterNewLine() {
+ return crAfterNewLine;
+ }
+
+ public void setCrAfterNewLine(boolean crAfterNewLine) {
+ this.crAfterNewLine = crAfterNewLine;
+ }
+
+ public List<IHyperlink> hyperlinksAt(int line) {
+ return text.hyperlinksAt(line);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
new file mode 100644
index 0000000..bf195a5
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
@@ -0,0 +1,368 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.emulator;
+
+import static java.util.Collections.emptyList;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+
+import com.google.eclipse.tm.internal.terminal.hyperlink.*;
+import com.google.eclipse.tm.terminal.model.*;
+
+public class VT100EmulatorBackend implements IVT100EmulatorBackend {
+ // This field holds the number of the column in which the cursor is logically positioned. The left-most column on the
+ // screen is column 0, and column numbers increase to the right. The maximum value of this field is
+ // widthInColumns - 1. We track the cursor column using this field to avoid having to recompute it repeatly using
+ // StyledText method calls.
+ //
+ // The StyledText widget that displays text has a vertical bar (called the "caret") that appears _between_ character
+ // cells, but ANSI terminals have the concept of a cursor that appears _in_ a character cell, so we need a convention
+ // for which character cell the cursor logically occupies when the caret is physically between two cells. The
+ // convention used in this class is that the cursor is logically in column N when the caret is physically positioned
+ // immediately to the _left_ of column N.
+ //
+ // When cursorColumn is N, the next character output to the terminal appears in column N. When a character is output
+ // to the rightmost column on a given line (column widthInColumns - 1), the cursor moves to column 0 on the next line
+ // after the character is drawn (this is how line wrapping is implemented). If the cursor is in the bottom-most line
+ // when line wrapping occurs, the topmost visible line is scrolled off the top edge of the screen.
+ private int cursorColumn;
+
+ private int cursorLine;
+ private Style defaultStyle;
+ private Style style;
+ private int lines;
+ private int columns;
+
+ private final ITerminalTextData terminal;
+
+ private final IHyperlinkFactory httpHyperlinkFactory = new HttpHyperlinkFactory();
+ private final Map<Integer, List<IHyperlink>> hyperlinks = new HashMap<Integer, List<IHyperlink>>();
+
+ public VT100EmulatorBackend(ITerminalTextData terminal) {
+ this.terminal = terminal;
+ }
+
+ @Override public void clearAll() {
+ synchronized (terminal) {
+ // clear the history
+ int n = terminal.getHeight();
+ for (int line = 0; line < n; line++) {
+ terminal.cleanLine(line);
+ }
+ terminal.setDimensions(lines, terminal.getWidth());
+ setStyle(getDefaultStyle());
+ setCursor(0, 0);
+ }
+ }
+
+ @Override public void setDimensions(int lines, int columns) {
+ synchronized (terminal) {
+ if (lines == this.lines && columns == this.columns) {
+ return; // nothing to do
+ }
+ // relative cursor line
+ int cursorLine = getCursorLine();
+ int cursorColumn = getCursorColumn();
+ int height = terminal.getHeight();
+ // absolute cursor line
+ int absoluteCursorLine = cursorLine + height - this.lines;
+ int newLines = Math.max(lines, height);
+ if (lines < this.lines) {
+ if (height == this.lines) {
+ // if the terminal has no history, then resize by setting the size to the new size.
+ // TODO We are assuming that cursor line points at end of text.
+ newLines = Math.max(lines, cursorLine + 1);
+ }
+ }
+ this.lines = lines;
+ this.columns = columns;
+ // Make the terminal at least as high as we need lines.
+ terminal.setDimensions(newLines, this.columns);
+ // Compute relative cursor line.
+ cursorLine = absoluteCursorLine - (newLines - this.lines);
+ setCursor(cursorLine, cursorColumn);
+ }
+ }
+
+ int toAbsoluteLine(int line) {
+ synchronized (terminal) {
+ return terminal.getHeight() - this.lines + line;
+ }
+ }
+
+ @Override public void insertCharacters(int charactersToInsert) {
+ synchronized (terminal) {
+ int line = toAbsoluteLine(cursorLine);
+ int n = charactersToInsert;
+ for (int column = columns - 1; column >= cursorColumn + n; column--) {
+ char c = terminal.getChar(line, column - n);
+ Style style = terminal.getStyle(line, column - n);
+ terminal.setChar(line, column, c, style);
+ }
+ int last = Math.min(cursorColumn + n, columns);
+ for (int col = cursorColumn; col < last; col++) {
+ terminal.setChar(line, col, '\000', null);
+ }
+ }
+ }
+
+ @Override public void eraseToEndOfScreen() {
+ synchronized (terminal) {
+ eraseLineToEnd();
+ for (int line = toAbsoluteLine(cursorLine + 1); line < toAbsoluteLine(lines); line++) {
+ terminal.cleanLine(line);
+ }
+ }
+ }
+
+ @Override public void eraseToCursor() {
+ synchronized (terminal) {
+ for (int line = toAbsoluteLine(0); line < toAbsoluteLine(cursorLine); line++) {
+ terminal.cleanLine(line);
+ }
+ eraseLineToCursor();
+ }
+ }
+
+ @Override public void eraseAll() {
+ synchronized (terminal) {
+ for (int line = toAbsoluteLine(0); line < toAbsoluteLine(lines); line++) {
+ terminal.cleanLine(line);
+ }
+ }
+ }
+
+ @Override public void eraseLine() {
+ synchronized (terminal) {
+ terminal.cleanLine(toAbsoluteLine(cursorLine));
+ }
+ }
+
+ @Override public void eraseLineToEnd() {
+ synchronized (terminal) {
+ int line = toAbsoluteLine(cursorLine);
+ for (int col = cursorColumn; col < columns; col++) {
+ terminal.setChar(line, col, '\000', null);
+ }
+ }
+ }
+
+ @Override public void eraseLineToCursor() {
+ synchronized (terminal) {
+ int line = toAbsoluteLine(cursorLine);
+ for (int col = 0; col <= cursorColumn; col++) {
+ terminal.setChar(line, col, '\000', null);
+ }
+ }
+ }
+
+ @Override public void insertLines(int lineCount) {
+ synchronized (terminal) {
+ if (!isCursorInScrollingRegion()) {
+ return;
+ }
+ Assert.isTrue(lineCount > 0);
+ int line = toAbsoluteLine(cursorLine);
+ int nLines = terminal.getHeight() - line;
+ terminal.scroll(line, nLines, lineCount);
+ }
+ }
+
+ @Override public void deleteCharacters(int charCount) {
+ synchronized (terminal) {
+ int line = toAbsoluteLine(cursorLine);
+ for (int col = cursorColumn + charCount; col < columns; col++) {
+ char c = terminal.getChar(line, col);
+ Style style = terminal.getStyle(line, col);
+ terminal.setChar(line, col - charCount, c, style);
+ }
+ int first = Math.max(cursorColumn, columns - charCount);
+ for (int col = first; col < columns; col++) {
+ terminal.setChar(line, col, '\000', null);
+ }
+ }
+ }
+
+ @Override public void deleteLines(int lineCount) {
+ synchronized (terminal) {
+ if (!isCursorInScrollingRegion()) {
+ return;
+ }
+ Assert.isTrue(lineCount > 0);
+ int line = toAbsoluteLine(cursorLine);
+ int currentLineCount = terminal.getHeight() - line;
+ terminal.scroll(line, currentLineCount, -lineCount);
+ }
+ }
+
+ private boolean isCursorInScrollingRegion() {
+ return true;
+ }
+
+ @Override public Style getDefaultStyle() {
+ synchronized (terminal) {
+ return defaultStyle;
+ }
+ }
+
+ @Override public void setDefaultStyle(Style defaultStyle) {
+ synchronized (terminal) {
+ this.defaultStyle = defaultStyle;
+ }
+ }
+
+ @Override public Style getStyle() {
+ synchronized (terminal) {
+ if (style == null) {
+ return defaultStyle;
+ }
+ return style;
+ }
+ }
+
+ @Override public void setStyle(Style style) {
+ synchronized (terminal) {
+ this.style = style;
+ }
+ }
+
+ @Override public void appendString(String buffer) {
+ synchronized (terminal) {
+ char[] chars = buffer.toCharArray();
+ int line = toAbsoluteLine(cursorLine);
+ int originalLine = line;
+ List<IHyperlink> found = emptyList();
+ if (buffer != null) {
+ found = httpHyperlinkFactory.hyperlinksIn(cursorColumn, buffer);
+ hyperlinks.put(new Integer(line), found);
+ }
+ int i = 0;
+ while (i < chars.length) {
+ int n = Math.min(columns - cursorColumn, chars.length - i);
+ terminal.setChars(line, cursorColumn, chars, i, n, style);
+ int col = cursorColumn + n;
+ i += n;
+ // wrap needed?
+ if (col >= columns) {
+ doNewline();
+ line = toAbsoluteLine(cursorLine);
+ setCursorColumn(0);
+ } else {
+ setCursorColumn(col);
+ }
+ }
+ drawHyperlinks(found, originalLine);
+ }
+ }
+
+ private void drawHyperlinks(List<IHyperlink> hyperlinks, int line) {
+ for (IHyperlink hyperlink : hyperlinks) {
+ IRegion region = hyperlink.getHyperlinkRegion();
+ int start = region.getOffset();
+ int end = start + region.getLength();
+ for (int column = start; column < end; column++) {
+ Style style = terminal.getStyle(line, column);
+ if (style != null) {
+ style = style.setUnderline(true);
+ terminal.setChar(line, column, terminal.getChar(line, column), style);
+ }
+ }
+ }
+ }
+
+ // MUST be called from a synchronized block!
+ private void doNewline() {
+ if (cursorLine + 1 >= lines) {
+ int h = terminal.getHeight();
+ terminal.addLine();
+ if (h != terminal.getHeight()) {
+ setCursorLine(cursorLine + 1);
+ }
+ } else {
+ setCursorLine(cursorLine + 1);
+ }
+ }
+
+ @Override public void processNewline() {
+ synchronized (terminal) {
+ doNewline();
+ }
+ }
+
+ @Override public int getCursorLine() {
+ synchronized (terminal) {
+ return cursorLine;
+ }
+ }
+
+ @Override public int getCursorColumn() {
+ synchronized (terminal) {
+ return cursorColumn;
+ }
+ }
+
+ @Override public void setCursor(int targetLine, int targetColumn) {
+ synchronized (terminal) {
+ setCursorLine(targetLine);
+ setCursorColumn(targetColumn);
+ }
+ }
+
+ @Override public void setCursorColumn(int targetColumn) {
+ synchronized (terminal) {
+ if (targetColumn < 0) {
+ targetColumn = 0;
+ } else if (targetColumn >= columns) {
+ targetColumn = columns - 1;
+ }
+ cursorColumn = targetColumn;
+ // We make the assumption that nobody is changing the
+ // terminal cursor except this class!
+ // This assumption gives a huge performance improvement
+ terminal.setCursorColumn(targetColumn);
+ }
+ }
+
+ @Override public void setCursorLine(int targetLine) {
+ synchronized (terminal) {
+ if (targetLine < 0) {
+ targetLine = 0;
+ } else if (targetLine >= lines) {
+ targetLine = lines - 1;
+ }
+ cursorLine = targetLine;
+ // We make the assumption that nobody is changing the terminal cursor except this class!
+ // This assumption gives a huge performance improvement.
+ terminal.setCursorLine(toAbsoluteLine(targetLine));
+ }
+ }
+
+ @Override public int getLines() {
+ synchronized (terminal) {
+ return lines;
+ }
+ }
+
+ @Override public int getColumns() {
+ synchronized (terminal) {
+ return columns;
+ }
+ }
+
+ @Override public List<IHyperlink> hyperlinksAt(int line) {
+ List<IHyperlink> found = hyperlinks.get(new Integer(line));
+ if (found == null) {
+ return emptyList();
+ }
+ return found;
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
new file mode 100644
index 0000000..8de88a1
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
@@ -0,0 +1,852 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.emulator;
+
+import static org.eclipse.core.runtime.Status.OK_STATUS;
+import static org.eclipse.jface.bindings.keys.SWTKeySupport.convertEventToUnmodifiedAccelerator;
+
+import static com.google.eclipse.tm.internal.terminal.control.impl.TerminalPlugin.isOptionEnabled;
+
+import java.io.*;
+import java.net.SocketException;
+import java.util.List;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.contexts.*;
+import org.eclipse.ui.keys.IBindingService;
+
+import com.google.eclipse.tm.internal.terminal.control.*;
+import com.google.eclipse.tm.internal.terminal.control.impl.*;
+import com.google.eclipse.tm.internal.terminal.provisional.api.*;
+import com.google.eclipse.tm.internal.terminal.textcanvas.*;
+import com.google.eclipse.tm.internal.terminal.textcanvas.PipedInputStream;
+import com.google.eclipse.tm.terminal.model.*;
+
+public class VT100TerminalControl implements ITerminalControlForText, ITerminalControl, ITerminalViewControl {
+ protected static final String[] LINE_DELIMITERS = { "\n" };
+
+ private static final String DEFAULT_ENCODING =
+ new InputStreamReader(new ByteArrayInputStream(new byte[0])).getEncoding();
+
+ // This field holds a reference to a TerminalText object that performs all ANSI text processing on data received from
+ // the remote host and controls how text is displayed using the view's StyledText widget.
+ private final VT100Emulator terminalText;
+
+ private Display display;
+ private TextCanvas textControl;
+ private Composite rootControl;
+ private Clipboard clipboard;
+ private KeyListener keyHandler;
+ private final ITerminalListener terminalListener;
+ private String message = "";
+ private FocusListener fFocusListener;
+ private ITerminalConnector connector;
+ private final ITerminalConnector[] connectors;
+ private final PipedInputStream inputStream;
+ private String encoding = DEFAULT_ENCODING;
+ private InputStreamReader inputStreamReader;
+ private ICommandInputField commandInputField;
+ private volatile TerminalState state;
+ private final ITerminalTextData terminalModel;
+
+ volatile private Job job;
+
+ private final EditActionAccelerators editActionAccelerators = new EditActionAccelerators();
+
+ public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
+ this.connectors = connectors;
+ terminalListener = target;
+ terminalModel = TerminalTextDataFactory.makeTerminalTextData();
+ terminalModel.setMaxHeight(1000);
+ inputStream = new PipedInputStream(8 * 1024);
+ terminalText = new VT100Emulator(terminalModel, this, null);
+ try {
+ // Use default Encoding as start, until setEncoding() is called.
+ setEncoding(null);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ // Fall back to local platform default encoding
+ encoding = DEFAULT_ENCODING;
+ inputStreamReader = new InputStreamReader(inputStream);
+ terminalText.setInputStreamReader(inputStreamReader);
+ }
+ setUpTerminal(wndParent);
+ }
+
+ @Override public void setEncoding(String encoding) throws UnsupportedEncodingException {
+ if (encoding == null) {
+ encoding = "ISO-8859-1";
+ }
+ inputStreamReader = new InputStreamReader(inputStream, encoding);
+ // remember encoding if above didn't throw an exception
+ this.encoding = encoding;
+ terminalText.setInputStreamReader(inputStreamReader);
+ }
+
+ @Override public String getEncoding() {
+ return encoding;
+ }
+
+ @Override public ITerminalConnector[] getConnectors() {
+ return connectors;
+ }
+
+ @Override public void copy() {
+ copy(DND.CLIPBOARD);
+ }
+
+ private void copy(int clipboardType) {
+ String selection = getSelection();
+ if (selection == null || selection.isEmpty()) {
+ return;
+ }
+ Object[] data = new Object[] { selection };
+ Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
+ clipboard.setContents(data, types, clipboardType);
+ }
+
+ @Override public void paste() {
+ paste(DND.CLIPBOARD);
+ }
+
+ private void paste(int clipboardType) {
+ TextTransfer textTransfer = TextTransfer.getInstance();
+ String strText = (String) clipboard.getContents(textTransfer, clipboardType);
+ pasteString(strText);
+ }
+
+ @Override public boolean pasteString(String text) {
+ if (!isConnected()) {
+ return false;
+ }
+ if (text == null) {
+ return false;
+ }
+ if (!encoding.equals(DEFAULT_ENCODING)) {
+ sendString(text);
+ } else {
+ // TODO I do not understand why pasteString would do this here...
+ for (int i = 0; i < text.length(); i++) {
+ sendChar(text.charAt(i), false);
+ }
+ }
+ return true;
+ }
+
+ @Override public void selectAll() {
+ getTextControl().selectAll();
+ }
+
+ @Override public void sendKey(char character) {
+ Event event;
+ KeyEvent keyEvent;
+ event = new Event();
+ event.widget = getTextControl();
+ event.character = character;
+ event.keyCode = 0;
+ event.stateMask = 0;
+ event.doit = true;
+ keyEvent = new KeyEvent(event);
+ keyHandler.keyPressed(keyEvent);
+ }
+
+ @Override public void clearTerminal() {
+ getTerminalText().clearTerminal();
+ }
+
+ @Override public Clipboard getClipboard() {
+ return clipboard;
+ }
+
+ @Override public String getSelection() {
+ String text = textControl.getSelectionText();
+ return text == null ? "" : text;
+ }
+
+ @Override public boolean setFocus() {
+ return getTextControl().setFocus();
+ }
+
+ @Override public boolean isEmpty() {
+ return getTextControl().isEmpty();
+ }
+
+ @Override public boolean isDisposed() {
+ return getTextControl().isDisposed();
+ }
+
+ @Override public boolean isConnected() {
+ return state == TerminalState.CONNECTED;
+ }
+
+ @Override public void disposeTerminal() {
+ disconnectTerminal();
+ clipboard.dispose();
+ getTerminalText().dispose();
+ }
+
+ @Override public void connectTerminal() {
+ if (getTerminalConnector() == null) {
+ return;
+ }
+ terminalText.resetState();
+ if (connector.getInitializationErrorMessage() != null) {
+ showErrorMessage(NLS.bind(TerminalMessages.cannotConnectTo, connector.getName(),
+ connector.getInitializationErrorMessage()));
+ return;
+ }
+ getTerminalConnector().connect(this);
+ // clean the error message
+ setErrorMessage("");
+ waitForConnect();
+ }
+
+ @Override public ITerminalConnector getTerminalConnector() {
+ return connector;
+ }
+
+ @Override public void disconnectTerminal() {
+ Logger.log("entered.");
+ // Disconnect the remote side first.
+ if (getState() != TerminalState.CLOSED && getTerminalConnector() != null) {
+ getTerminalConnector().disconnect();
+ }
+ // Ensure that a new Job can be started; then clean up old Job.
+ Job newJob;
+ synchronized (this) {
+ newJob = job;
+ job = null;
+ }
+ if (newJob != null) {
+ newJob.cancel();
+ // Join job to avoid leaving job running after workbench shutdown (333613).
+ // Interrupt to be fast enough; cannot close fInputStream since it is re-used (bug 348700).
+ Thread t = newJob.getThread();
+ if (t != null) {
+ t.interrupt();
+ }
+ try {
+ newJob.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ private void waitForConnect() {
+ // TODO
+ // Eliminate this code
+ while (getState() == TerminalState.CONNECTING) {
+ if (display.readAndDispatch()) {
+ continue;
+ }
+ display.sleep();
+ }
+ if (getTextControl().isDisposed()) {
+ disconnectTerminal();
+ return;
+ }
+ if (!getMsg().isEmpty()) {
+ showErrorMessage(getMsg());
+ disconnectTerminal();
+ return;
+ }
+ getTextControl().setFocus();
+ startReaderJob();
+ }
+
+ private synchronized void startReaderJob() {
+ if (job == null) {
+ initializeJob();
+ job.setSystem(true);
+ job.schedule();
+ }
+ }
+
+ private void initializeJob() {
+ job = new Job("Terminal data reader") {
+ @Override protected IStatus run(IProgressMonitor monitor) {
+ IStatus status = OK_STATUS;
+ try {
+ while (true) {
+ while (inputStream.available() == 0 && !monitor.isCanceled()) {
+ try {
+ inputStream.waitForAvailable(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ if (monitor.isCanceled()) {
+ // Do not disconnect terminal here because another reader job may already be running.
+ status = Status.CANCEL_STATUS;
+ break;
+ }
+ try {
+ // TODO: should block when no text is available!
+ terminalText.processText();
+ } catch (Exception e) {
+ disconnectTerminal();
+ status = new Status(IStatus.ERROR, TerminalPlugin.PLUGIN_ID, e.getLocalizedMessage(), e);
+ break;
+ }
+ }
+ } finally {
+ // Clean the job: start a new one when the connection gets restarted.
+ // Bug 208145: make sure we do not clean an other job that's already started (since it would become a zombie)
+ synchronized (VT100TerminalControl.this) {
+ if (job == this) {
+ job = null;
+ }
+ }
+ }
+ return status;
+ }
+ };
+ }
+
+ private void showErrorMessage(String message) {
+ String title = TerminalMessages.terminalError;
+ MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
+ mb.setText(title);
+ mb.setMessage(message);
+ mb.open();
+ }
+
+ protected void sendString(String string) {
+ try {
+ // Send the string after converting it to an array of bytes using the platform's default character encoding.
+ //
+ // TODO: Find a way to force this to use the ISO Latin-1 encoding.
+ // TODO: handle Encoding Errors in a better way
+ getOutputStream().write(string.getBytes(encoding));
+ getOutputStream().flush();
+ } catch (SocketException socketException) {
+ displayTextInTerminal(socketException.getMessage());
+ String strMsg = TerminalMessages.socketError + "!\n" + socketException.getMessage();
+ showErrorMessage(strMsg);
+ Logger.logException(socketException);
+ disconnectTerminal();
+ } catch (IOException ioException) {
+ showErrorMessage(TerminalMessages.ioError + "!\n" + ioException.getMessage());
+ Logger.logException(ioException);
+ disconnectTerminal();
+ }
+ }
+
+ @Override public Shell getShell() {
+ return getTextControl().getShell();
+ }
+
+ protected void sendChar(char chKey, boolean altKeyPressed) {
+ try {
+ int byteToSend = chKey;
+ OutputStream os = getOutputStream();
+ if (os == null) {
+ // Bug 207785: NPE when trying to send char while no longer connected
+ Logger.log("NOT sending '" + byteToSend + "' because no longer connected");
+ } else {
+ if (altKeyPressed) {
+ // When the ALT key is pressed at the same time that a character is typed, translate it into an ESCAPE
+ // followed by the character. The alternative in this case is to set the high bit of the character being
+ // transmitted, but that will cause input such as ALT-f to be seen as the ISO Latin-1 character '�', which
+ // can be confusing to European users running Emacs, for whom Alt-f should move forward a word instead of
+ // inserting the '�' character.
+ //
+ // TODO: Make the ESCAPE-vs-highbit behavior user configurable.
+ Logger.log("sending ESC + '" + byteToSend + "'");
+ getOutputStream().write('\u001b');
+ getOutputStream().write(byteToSend);
+ } else {
+ Logger.log("sending '" + byteToSend + "'");
+ getOutputStream().write(byteToSend);
+ }
+ getOutputStream().flush();
+ }
+ } catch (SocketException socketException) {
+ Logger.logException(socketException);
+ displayTextInTerminal(socketException.getMessage());
+ String message = TerminalMessages.socketError + "!\n" + socketException.getMessage();
+ showErrorMessage(message);
+ Logger.logException(socketException);
+ disconnectTerminal();
+ } catch (IOException ioException) {
+ Logger.logException(ioException);
+ displayTextInTerminal(ioException.getMessage());
+ String message = TerminalMessages.ioError + "!\n" + ioException.getMessage();
+ showErrorMessage(message);
+ Logger.logException(ioException);
+ disconnectTerminal();
+ }
+ }
+
+ @Override public void setUpTerminal(Composite parent) {
+ Assert.isNotNull(parent);
+ state = TerminalState.CLOSED;
+ setUpControls(parent);
+ setupListeners();
+ setupHelp(rootControl, TerminalPlugin.HELP_VIEW);
+ }
+
+ @Override public void setFont(Font font) {
+ getTextControl().setFont(font);
+ if (commandInputField != null) {
+ commandInputField.setFont(font);
+ }
+ // Tell the TerminalControl singleton that the font has changed.
+ textControl.onFontChange();
+ getTerminalText().fontChanged();
+ }
+
+ @Override public Font getFont() {
+ return getTextControl().getFont();
+ }
+
+ @Override public Control getControl() {
+ return textControl;
+ }
+
+ @Override public Control getRootControl() {
+ return rootControl;
+ }
+
+ protected void setUpControls(Composite parent) {
+ // The Terminal view now aims to be an ANSI-conforming terminal emulator, so it can't have a horizontal scroll bar
+ // (but a vertical one is ok). Also, do _not_ make the TextViewer read-only, because that prevents it from seeing a
+ // TAB character when the user presses TAB (instead, the TAB causes focus to switch to another Workbench control).
+ // We prevent local keyboard input from modifying the text in method TerminalVerifyKeyListener.verifyKey().
+ rootControl = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ layout.verticalSpacing = 0;
+ rootControl.setLayout(layout);
+ ITerminalTextDataSnapshot snapshot = terminalModel.makeSnapshot();
+ // TODO how to get the initial size correctly!
+ snapshot.updateSnapshot(false);
+ ITextCanvasModel canvasModel = new PollingTextCanvasModel(snapshot);
+ textControl = new TextCanvas(rootControl, canvasModel, SWT.NONE, new TextLineRenderer(textControl, canvasModel));
+ textControl.addMouseListener(new MouseAdapter() {
+ @Override public void mouseUp(MouseEvent e) {
+ IHyperlink hyperlink = hyperlinkAt(e);
+ if (hyperlink != null) {
+ hyperlink.open();
+ }
+ }
+ });
+ textControl.addMouseMoveListener(new MouseMoveListener() {
+ @Override public void mouseMove(MouseEvent e) {
+ IHyperlink hyperlink = hyperlinkAt(e);
+ int cursorId = (hyperlink == null) ? SWT.CURSOR_IBEAM : SWT.CURSOR_HAND;
+ Cursor newCursor = textControl.getDisplay().getSystemCursor(cursorId);
+ if (!newCursor.equals(textControl.getCursor())) {
+ textControl.setCursor(newCursor);
+ }
+ }
+ });
+ textControl.setLayoutData(new GridData(GridData.FILL_BOTH));
+ textControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ textControl.addResizeHandler(new TextCanvas.ResizeListener() {
+ @Override public void sizeChanged(int lines, int columns) {
+ terminalText.setDimensions(lines, columns);
+ }
+ });
+ textControl.addMouseListener(new MouseAdapter() {
+ @Override public void mouseUp(MouseEvent e) {
+ // update selection used by middle mouse button paste
+ if (e.button == 1 && getSelection().length() > 0) {
+ copy(DND.SELECTION_CLIPBOARD);
+ }
+ }
+ });
+ display = getTextControl().getDisplay();
+ clipboard = new Clipboard(display);
+ setFont(JFaceResources.getTextFont());
+ }
+
+ private IHyperlink hyperlinkAt(MouseEvent e) {
+ Point p = textControl.screenPointToCell(e.x, e.y);
+ if (p != null) {
+ List<IHyperlink> hyperlinks = terminalText.hyperlinksAt(p.y);
+ for (IHyperlink hyperlink : hyperlinks) {
+ IRegion region = hyperlink.getHyperlinkRegion();
+ int start = region.getOffset();
+ int end = start + region.getLength() - 1;
+ if (p.x >= start && p.x <= end) {
+ return hyperlink;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected void setupListeners() {
+ keyHandler = new TerminalKeyHandler();
+ fFocusListener = new TerminalFocusListener();
+ getTextControl().addKeyListener(keyHandler);
+ getTextControl().addFocusListener(fFocusListener);
+ }
+
+ /**
+ * Setup all the help contexts for the controls.
+ */
+ protected void setupHelp(Composite parent, String id) {
+ Control[] children = parent.getChildren();
+ for (int nIndex = 0; nIndex < children.length; nIndex++) {
+ if (children[nIndex] instanceof Composite) {
+ setupHelp((Composite) children[nIndex], id);
+ }
+ }
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, id);
+ }
+
+ @Override public void displayTextInTerminal(String text) {
+ writeToTerminal("\r\n" + text + "\r\n");
+ }
+
+ private void writeToTerminal(String text) {
+ try {
+ getRemoteToTerminalOutputStream().write(text.getBytes(encoding));
+ } catch (UnsupportedEncodingException e) {
+ // should never happen!
+ e.printStackTrace();
+ } catch (IOException e) {
+ // should never happen!
+ e.printStackTrace();
+ }
+ }
+
+ @Override public OutputStream getRemoteToTerminalOutputStream() {
+ if (Logger.isLogEnabled()) {
+ return new LoggingOutputStream(inputStream.getOutputStream());
+ }
+ return inputStream.getOutputStream();
+ }
+
+ protected boolean isLogCharEnabled() {
+ return isOptionEnabled(Logger.TRACE_DEBUG_LOG_CHAR);
+ }
+
+ protected boolean isLogBufferSizeEnabled() {
+ return isOptionEnabled(Logger.TRACE_DEBUG_LOG_BUFFER_SIZE);
+ }
+
+ @Override public OutputStream getOutputStream() {
+ if (getTerminalConnector() != null) {
+ return getTerminalConnector().getTerminalToRemoteStream();
+ }
+ return null;
+ }
+
+ @Override public void setErrorMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMsg() {
+ return message;
+ }
+
+ protected TextCanvas getTextControl() {
+ return textControl;
+ }
+
+ public VT100Emulator getTerminalText() {
+ return terminalText;
+ }
+
+ protected class TerminalFocusListener implements FocusListener {
+ private IContextActivation contextActivation = null;
+
+ @Override public void focusGained(FocusEvent event) {
+ // Disable all keyboard accelerators (e.g., Control-B) so the Terminal view can see every key stroke. Without
+ // this, Emacs, vi, and Bash are unusable in the terminal view.
+ IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
+ bindingService.setKeyFilterEnabled(false);
+ // The above code fails to cause Eclipse to disable menu-activation accelerators (e.g., Alt-F for the File menu),
+ // so we set the command context to be the Terminal view's command context. This enables us to override
+ // menu-activation accelerators with no-op commands in our plugin.xml file, which enables the terminal view to see
+ // absolutly _all_ key-presses.
+ IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
+ contextActivation = contextService.activateContext("org.eclipse.tm.terminal.TerminalContext");
+ }
+
+ @Override public void focusLost(FocusEvent event) {
+ // Enable all key bindings.
+ IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
+ bindingService.setKeyFilterEnabled(true);
+ // Restore the command context to its previous value.
+ IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
+ contextService.deactivateContext(contextActivation);
+ }
+ }
+
+ protected class TerminalKeyHandler extends KeyAdapter {
+ @Override public void keyPressed(KeyEvent event) {
+ if (getState() == TerminalState.CONNECTING) {
+ return;
+ }
+ int accelerator = convertEventToUnmodifiedAccelerator(event);
+ if (editActionAccelerators.isCopyAction(accelerator)) {
+ copy();
+ return;
+ }
+ if (editActionAccelerators.isPasteAction(accelerator)) {
+ paste();
+ return;
+ }
+ // We set the event.doit to false to prevent any further processing of this key event. The only reason this is
+ // here is because I was seeing the F10 key both send an escape sequence (due to this method) and switch focus to
+ // the Workbench File menu (forcing the user to click in the terminal view again to continue entering text). This
+ // fixes that.
+ event.doit = false;
+ char character = event.character;
+ if (state == TerminalState.CLOSED) {
+ // Pressing ENTER while not connected causes us to connect.
+ if (character == '\r') {
+ connectTerminal();
+ return;
+ }
+ // Ignore all other keyboard input when not connected.
+ // Allow other key handlers (such as Ctrl+F1) do their work.
+ event.doit = true;
+ return;
+ }
+ // Manage the Del key
+ if (event.keyCode == 0x000007f) {
+ sendString("\u001b[3~");
+ return;
+ }
+ // If the event character is NUL ('\u0000'), then a special key was pressed (e.g., PageUp, PageDown, an arrow key,
+ // a function key, Shift, Alt, Control, etc.). The one exception is when the user presses Control-@, which sends a
+ // NUL character, in which case we must send the NUL to the remote endpoint. This is necessary so that Emacs will
+ // work correctly, because Control-@ (i.e., NUL) invokes Emacs' set-mark-command when Emacs is running on a
+ // terminal. When the user presses Control-@, the keyCode is 50.
+ if (character == '\u0000' && event.keyCode != 50) {
+ // A special key was pressed. Figure out which one it was and send the appropriate ANSI escape sequence.
+ //
+ // IMPORTANT: Control will not enter this method for these special keys unless certain <keybinding> tags are
+ // present in the plugin.xml file for the Terminal view. Do not delete those tags.
+ switch (event.keyCode) {
+ case 0x1000001: // Up arrow.
+ sendString("\u001b[A");
+ break;
+ case 0x1000002: // Down arrow.
+ sendString("\u001b[B");
+ break;
+ case 0x1000003: // Left arrow.
+ sendString("\u001b[D");
+ break;
+ case 0x1000004: // Right arrow.
+ sendString("\u001b[C");
+ break;
+ case 0x1000005: // PgUp key.
+ sendString("\u001b[5~");
+ break;
+ case 0x1000006: // PgDn key.
+ sendString("\u001b[6~");
+ break;
+ case 0x1000007: // Home key.
+ sendString("\u001b[H");
+ break;
+ case 0x1000008: // End key.
+ sendString("\u001b[F");
+ break;
+ case 0x1000009: // Insert.
+ sendString("\u001b[2~");
+ break;
+ case 0x100000a: // F1 key.
+ if ((event.stateMask & SWT.CTRL) != 0) {
+ // Allow Ctrl+F1 to act locally as well as on the remote, because it is typically non-intrusive
+ event.doit = true;
+ }
+ sendString("\u001b[M");
+ break;
+ case 0x100000b: // F2 key.
+ sendString("\u001b[N");
+ break;
+ case 0x100000c: // F3 key.
+ sendString("\u001b[O");
+ break;
+ case 0x100000d: // F4 key.
+ sendString("\u001b[P");
+ break;
+ case 0x100000e: // F5 key.
+ sendString("\u001b[Q");
+ break;
+ case 0x100000f: // F6 key.
+ sendString("\u001b[R");
+ break;
+ case 0x1000010: // F7 key.
+ sendString("\u001b[S");
+ break;
+ case 0x1000011: // F8 key.
+ sendString("\u001b[T");
+ break;
+ case 0x1000012: // F9 key.
+ sendString("\u001b[U");
+ break;
+ case 0x1000013: // F10 key.
+ sendString("\u001b[V");
+ break;
+ case 0x1000014: // F11 key.
+ sendString("\u001b[W");
+ break;
+ case 0x1000015: // F12 key.
+ sendString("\u001b[X");
+ break;
+ default:
+ // Ignore other special keys. Control flows through this case when the user presses SHIFT, CONTROL, ALT, and
+ // any other key not handled by the above cases.
+ break;
+ }
+ // It's ok to return here, because we never locally echo special keys.
+ return;
+ }
+ // To fix SPR 110341, we consider the Alt key to be pressed only when the Control key is _not_ also pressed. This
+ // works around a bug in SWT where, on European keyboards, the AltGr key being pressed appears to us as Control
+ // + Alt being pressed simultaneously.
+ Logger.log("stateMask = " + event.stateMask);
+ boolean altKeyPressed = (((event.stateMask & SWT.ALT) != 0) && ((event.stateMask & SWT.CTRL) == 0));
+ if (!altKeyPressed && (event.stateMask & SWT.CTRL) != 0 && character == ' ') {
+ // Send a NUL character -- many terminal emulators send NUL when Control-Space is pressed. This is used to set
+ // the mark in Emacs.
+ character = '\u0000';
+ }
+ sendChar(character, altKeyPressed);
+ // Special case: When we are in a TCP connection and echoing characters locally, send a LF after sending a CR.
+ // ISSUE: Is this absolutely required?
+ if (character == '\r' && getTerminalConnector() != null && isConnected() && getTerminalConnector().isLocalEcho()) {
+ sendChar('\n', false);
+ }
+ // Now decide if we should locally echo the character we just sent. We do _not_ locally echo the character if any
+ // of these conditions are true:
+ //
+ // * This is a serial connection.
+ // * This is a TCP connection (i.e., m_telnetConnection is not null) and the remote endpoint is not a TELNET
+ // server.
+ // * The ALT (or META) key is pressed.
+ // * The character is any of the first 32 ISO Latin-1 characters except Control-I or Control-M.
+ // * The character is the DELETE character.
+ if (getTerminalConnector() == null || getTerminalConnector().isLocalEcho() == false || altKeyPressed
+ || (character >= '\u0001' && character < '\t') || (character > '\t' && character < '\r')
+ || (character > '\r' && character <= '\u001f') || character == '\u007f') {
+ // No local echoing.
+ return;
+ }
+ // Locally echo the character.
+ StringBuilder charBuffer = new StringBuilder();
+ charBuffer.append(character);
+ // If the character is a carriage return, we locally echo it as a CR + LF combination.
+ if (character == '\r') {
+ charBuffer.append('\n');
+ }
+ writeToTerminal(charBuffer.toString());
+ }
+ }
+
+ @Override public void setTerminalTitle(String title) {
+ terminalListener.setTerminalTitle(title);
+ }
+
+ @Override public TerminalState getState() {
+ return state;
+ }
+
+ @Override public void setState(TerminalState state) {
+ this.state = state;
+ terminalListener.setState(state);
+ // enable the (blinking) cursor if the terminal is connected
+ runAsyncInDisplayThread(new Runnable() {
+ @Override public void run() {
+ if (textControl != null && !textControl.isDisposed()) {
+ textControl.setCursorEnabled(isConnected());
+ }
+ }
+ });
+ }
+
+ private void runAsyncInDisplayThread(Runnable runnable) {
+ if (Display.findDisplay(Thread.currentThread()) != null) {
+ runnable.run();
+ } else if (PlatformUI.isWorkbenchRunning()) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
+ // else should not happen and we ignore it...
+ }
+ }
+
+ @Override public String getSettingsSummary() {
+ if (getTerminalConnector() != null) {
+ return getTerminalConnector().getSettingsSummary();
+ }
+ return "";
+ }
+
+ @Override public void setConnector(ITerminalConnector connector) {
+ this.connector = connector;
+ }
+
+ @Override public ICommandInputField getCommandInputField() {
+ return commandInputField;
+ }
+
+ @Override public void setCommandInputField(ICommandInputField inputField) {
+ if (commandInputField != null) {
+ commandInputField.dispose();
+ }
+ commandInputField = inputField;
+ if (commandInputField != null) {
+ commandInputField.createControl(rootControl, this);
+ }
+ if (rootControl.isVisible()) {
+ rootControl.layout(true);
+ }
+ }
+
+ @Override public int getBufferLineLimit() {
+ return terminalModel.getMaxHeight();
+ }
+
+ @Override public void setBufferLineLimit(int bufferLineLimit) {
+ if (bufferLineLimit <= 0) {
+ return;
+ }
+ synchronized (terminalModel) {
+ if (terminalModel.getHeight() > bufferLineLimit) {
+ terminalModel.setDimensions(bufferLineLimit, terminalModel.getWidth());
+ }
+ terminalModel.setMaxHeight(bufferLineLimit);
+ }
+ }
+
+ @Override public boolean isScrollLockOn() {
+ return textControl.isScrollLockOn();
+ }
+
+ @Override public void setScrollLockOn(boolean on) {
+ textControl.setScrollLockOn(on);
+ }
+
+ @Override public void setInvertedColors(boolean invert) {
+ textControl.setInvertedColors(invert);
+ }
+
+ public void setColors(RGB background, RGB foreground) {
+ textControl.setColors(background, foreground);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/HttpHyperlinkFactory.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/HttpHyperlinkFactory.java
similarity index 85%
rename from com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/HttpHyperlinkFactory.java
rename to com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/HttpHyperlinkFactory.java
index 0a6a04b..3079dd4 100644
--- a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/HttpHyperlinkFactory.java
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/HttpHyperlinkFactory.java
@@ -6,7 +6,7 @@
*
* http://www.eclipse.org/legal/epl-v10.html
*/
-package com.google.eclipse.terminal.ui.hyperlink;
+package com.google.eclipse.tm.internal.terminal.hyperlink;
import java.util.*;
import java.util.regex.*;
@@ -18,7 +18,8 @@
* @author alruiz@google.com (Alex Ruiz)
*/
public class HttpHyperlinkFactory implements IHyperlinkFactory {
- private static Pattern URL_PATTERN = Pattern.compile("http(s)?:\\/{2}[\\d\\w-]+(\\.[\\d\\w-]+)*(?:(?:\\/[^\\s/]*))*(\\:[\\d]+)?"); //$NON-NLS-1$
+ private static Pattern URL_PATTERN =
+ Pattern.compile("http(s)?:\\/{2}[\\d\\w-]+(\\.[\\d\\w-]+)*(?:(?:\\/[^\\s/]*))*(\\:[\\d]+)?");
@Override public List<IHyperlink> hyperlinksIn(int column, String text) {
if (text == null) {
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/IHyperlinkFactory.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/IHyperlinkFactory.java
similarity index 90%
rename from com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/IHyperlinkFactory.java
rename to com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/IHyperlinkFactory.java
index cb9688a..11363cb 100644
--- a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/IHyperlinkFactory.java
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/IHyperlinkFactory.java
@@ -6,7 +6,7 @@
*
* http://www.eclipse.org/legal/epl-v10.html
*/
-package com.google.eclipse.terminal.ui.hyperlink;
+package com.google.eclipse.tm.internal.terminal.hyperlink;
import static java.util.Collections.emptyList;
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/UrlHyperlink.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/UrlHyperlink.java
similarity index 89%
rename from com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/UrlHyperlink.java
rename to com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/UrlHyperlink.java
index ba63446..e9a4992 100644
--- a/com.google.eclipse.tm.terminal/src/com/google/eclipse/terminal/ui/hyperlink/UrlHyperlink.java
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/hyperlink/UrlHyperlink.java
@@ -6,16 +6,17 @@
*
* http://www.eclipse.org/legal/epl-v10.html
*/
-package com.google.eclipse.terminal.ui.hyperlink;
+package com.google.eclipse.tm.internal.terminal.hyperlink;
import java.net.*;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.URLHyperlink;
-import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
import org.eclipse.ui.*;
import org.eclipse.ui.browser.*;
+import com.google.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
+
/**
* @author alruiz@google.com (Alex Ruiz)
*/
@@ -55,7 +56,7 @@
private void logErrorOpeningUrl(Exception e) {
e.printStackTrace();
- String format = "Unable to open URL '%s'"; //$NON-NLS-1$
+ String format = "Unable to open URL '%s'";
TerminalPlugin.log(String.format(format, getURLString()), e);
}
}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/ISnapshotChanges.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/ISnapshotChanges.java
new file mode 100644
index 0000000..9e4b6a1
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/ISnapshotChanges.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import com.google.eclipse.tm.terminal.model.ITerminalTextData;
+
+public interface ISnapshotChanges {
+ void markLineChanged(int line);
+
+ void markLinesChanged(int line, int size);
+
+ /**
+ * Marks all lines within the scrolling region changed and resets the scrolling information.
+ */
+ void convertScrollingIntoChanges();
+
+ boolean hasChanged();
+
+ void scroll(int startLine, int size, int shift);
+
+ void setAllChanged(int height);
+
+ int getFirstChangedLine();
+
+ int getLastChangedLine();
+
+ int getScrollWindowStartLine();
+
+ int getScrollWindowSize();
+
+ int getScrollWindowShift();
+
+ boolean hasLineChanged(int line);
+
+ void markDimensionsChanged();
+
+ boolean hasDimensionsChanged();
+
+ void markCursorChanged();
+
+ boolean hasTerminalChanged();
+
+ void setTerminalChanged();
+
+ void copyChangedLines(ITerminalTextData destination, ITerminalTextData source);
+
+ void setInterestWindow(int startLine, int size);
+
+ int getInterestWindowStartLine();
+
+ int getInterestWindowSize();
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/SnapshotChanges.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/SnapshotChanges.java
new file mode 100644
index 0000000..dec2197
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/SnapshotChanges.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import org.eclipse.core.runtime.Assert;
+
+import com.google.eclipse.tm.terminal.model.ITerminalTextData;
+
+/**
+ * Collects the changes of the {@link ITerminalTextData}.
+ */
+public class SnapshotChanges implements ISnapshotChanges {
+ private int firstChangedLine;
+ private int lastChangedLine;
+ private int scrollWindowStartLine;
+ private int scrollWindowSize;
+ private int scrollWindowShift;
+ private boolean dontTrackScrolling;
+ private boolean[] changedLines;
+ private int interestWindowSize;
+ private int interestWindowStartLine;
+ private boolean fDimensionsChanged;
+ private boolean fTerminalHasChanged;
+ private boolean cursorHasChanged;
+
+ public SnapshotChanges(int windowStart, int windowSize) {
+ this(windowStart + windowSize);
+ interestWindowStartLine = windowStart;
+ interestWindowSize = windowSize;
+ }
+
+ public SnapshotChanges(int changedLineCount) {
+ setChangedLineCount(changedLineCount);
+ firstChangedLine = Integer.MAX_VALUE;
+ lastChangedLine = -1;
+ }
+
+ // Indicates whether the range overlaps with the interest window.
+ private boolean isInInterestWindow(int line, int size) {
+ if (interestWindowSize <= 0) {
+ return true;
+ }
+ if (line + size <= interestWindowStartLine || line >= interestWindowStartLine + interestWindowSize) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isInInterestWindow(int line) {
+ if (interestWindowSize <= 0) {
+ return true;
+ }
+ if (line < interestWindowStartLine || line >= interestWindowStartLine + interestWindowSize) {
+ return false;
+ }
+ return true;
+ }
+
+ private int fitLineToWindow(int line) {
+ if (interestWindowSize <= 0) {
+ return line;
+ }
+ if (line < interestWindowStartLine) {
+ return interestWindowStartLine;
+ }
+ return line;
+ }
+
+ /**
+ * The result is only defined if {@link #isInInterestWindow(int, int)} returns {@code true}.
+ * <p>
+ * Note:{@link #fitLineToWindow(int)} has to be called on the line to move the window correctly.
+ * </p>
+ * @param line the line <b>before</b> {@link #fitLineToWindow(int)} has been called.
+ * @param size
+ * @return the adjusted size.
+ */
+ private int fitSizeToWindow(int line, int size) {
+ if (interestWindowSize <= 0) {
+ return size;
+ }
+ if (line < interestWindowStartLine) {
+ size -= interestWindowStartLine - line;
+ line = interestWindowStartLine;
+ }
+ if (line + size > interestWindowStartLine + interestWindowSize) {
+ size = interestWindowStartLine + interestWindowSize - line;
+ }
+ return size;
+ }
+
+ @Override public void markLineChanged(int line) {
+ if (!isInInterestWindow(line)) {
+ return;
+ }
+ line = fitLineToWindow(line);
+ if (line < firstChangedLine) {
+ firstChangedLine = line;
+ }
+ if (line > lastChangedLine) {
+ lastChangedLine = line;
+ }
+ // In case the terminal got resized we expand don't remember the changed line because there is nothing to copy.
+ if (line < getChangedLineCount()) {
+ setChangedLine(line, true);
+ }
+ }
+
+ @Override public void markLinesChanged(int line, int size) {
+ if (size <= 0 || !isInInterestWindow(line, size)) {
+ return;
+ }
+ // Do not exceed the bounds of changedLines. The terminal might have been resized and we can only keep changes for
+ // the size of the previous terminal.
+ size = fitSizeToWindow(line, size);
+ line = fitLineToWindow(line);
+ int m = Math.min(line + size, getChangedLineCount());
+ for (int i = line; i < m; i++) {
+ setChangedLine(i, true);
+ }
+ // this sets firstChangedLine as well
+ markLineChanged(line);
+ // this sets lastChangedLine as well
+ markLineChanged(line + size - 1);
+ }
+
+ @Override public void markCursorChanged() {
+ cursorHasChanged = true;
+ }
+
+ @Override public void convertScrollingIntoChanges() {
+ markLinesChanged(scrollWindowStartLine, scrollWindowSize);
+ scrollWindowStartLine = 0;
+ scrollWindowSize = 0;
+ scrollWindowShift = 0;
+ }
+
+ @Override public boolean hasChanged() {
+ if (firstChangedLine != Integer.MAX_VALUE || lastChangedLine > 0 || scrollWindowShift != 0 || fDimensionsChanged
+ || cursorHasChanged) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override public void markDimensionsChanged() {
+ fDimensionsChanged = true;
+ }
+
+ @Override public boolean hasDimensionsChanged() {
+ return fDimensionsChanged;
+ }
+
+ @Override public boolean hasTerminalChanged() {
+ return fTerminalHasChanged;
+ }
+
+ @Override public void setTerminalChanged() {
+ fTerminalHasChanged = true;
+ }
+
+ @Override public void scroll(int startLine, int size, int shift) {
+ size = fitSizeToWindow(startLine, size);
+ startLine = fitLineToWindow(startLine);
+ // Let's track only negative shifts.
+ if (dontTrackScrolling) {
+ // We are in a state where we cannot track scrolling so let's simply mark the scrolled lines as changed.
+ markLinesChanged(startLine, size);
+ } else if (shift >= 0) {
+ // We cannot handle positive scroll forget about clever caching of scroll events.
+ doNotTrackScrollingAnymore();
+ // Mark all lines inside the scroll region as changed.
+ markLinesChanged(startLine, size);
+ } else {
+ // We have already scrolled.
+ if (scrollWindowShift < 0) {
+ // We have already scrolled.
+ if (scrollWindowStartLine == startLine && scrollWindowSize == size) {
+ // We are scrolling the same region again?
+ scrollWindowShift += shift;
+ scrollChangesLinesWithNegativeShift(startLine, size, shift);
+ } else {
+ // Mark all lines in the old scroll region as changed.
+ doNotTrackScrollingAnymore();
+ markLinesChanged(startLine, size);
+ }
+ } else {
+ // First scroll in this change -- we just notify it
+ scrollWindowStartLine = startLine;
+ scrollWindowSize = size;
+ scrollWindowShift = shift;
+ scrollChangesLinesWithNegativeShift(startLine, size, shift);
+ }
+ }
+ }
+
+ // Some incompatible scrolling occurred. We cannot do the scroll optimization anymore.
+ private void doNotTrackScrollingAnymore() {
+ if (scrollWindowSize > 0) {
+ // Convert the current scrolling into changes.
+ markLinesChanged(scrollWindowStartLine, scrollWindowSize);
+ scrollWindowStartLine = 0;
+ scrollWindowSize = 0;
+ scrollWindowShift = 0;
+ }
+ // Don't be clever on scrolling anymore.
+ dontTrackScrolling = true;
+ }
+
+ private void scrollChangesLinesWithNegativeShift(int line, int n, int shift) {
+ Assert.isTrue(shift < 0);
+ // Scroll the region. Don't run out of bounds!
+ int m = Math.min(line + n + shift, getChangedLineCount() + shift);
+ for (int i = line; i < m; i++) {
+ setChangedLine(i, hasLineChanged(i - shift));
+ // Move the first changed line up. We don't have to move the maximum down, because with a shift scroll, the max is
+ // moved by the next loop in this method
+ if (i < firstChangedLine && hasLineChanged(i)) {
+ firstChangedLine = i;
+ }
+ }
+ // Mark the "opened" lines as changed.
+ for (int i = Math.max(0, line + n + shift); i < line + n; i++) {
+ markLineChanged(i);
+ }
+ }
+
+ @Override public void setAllChanged(int height) {
+ scrollWindowStartLine = 0;
+ scrollWindowSize = 0;
+ scrollWindowShift = 0;
+ firstChangedLine = fitLineToWindow(0);
+ lastChangedLine = firstChangedLine + fitSizeToWindow(0, height) - 1;
+ // No need to keep an array of changes anymore.
+ setChangedLineCount(0);
+ }
+
+ @Override public int getFirstChangedLine() {
+ return firstChangedLine;
+ }
+
+ @Override public int getLastChangedLine() {
+ return lastChangedLine;
+ }
+
+ @Override public int getScrollWindowStartLine() {
+ return scrollWindowStartLine;
+ }
+
+ @Override public int getScrollWindowSize() {
+ return scrollWindowSize;
+ }
+
+ @Override public int getScrollWindowShift() {
+ return scrollWindowShift;
+ }
+
+ @Override public void copyChangedLines(ITerminalTextData destination, ITerminalTextData source) {
+ int n = Math.min(lastChangedLine + 1, source.getHeight());
+ for (int i = firstChangedLine; i < n; i++) {
+ if (hasLineChanged(i)) {
+ destination.copyLine(source, i, i);
+ }
+ }
+ }
+
+ @Override public int getInterestWindowSize() {
+ return interestWindowSize;
+ }
+
+ @Override public int getInterestWindowStartLine() {
+ return interestWindowStartLine;
+ }
+
+ @Override public void setInterestWindow(int startLine, int size) {
+ int oldStartLine = interestWindowStartLine;
+ int oldSize = interestWindowSize;
+ interestWindowStartLine = startLine;
+ interestWindowSize = size;
+ if (oldSize > 0) {
+ int shift = oldStartLine - startLine;
+ if (shift == 0) {
+ if (size > oldSize) {
+ // add lines to the end
+ markLinesChanged(oldStartLine + oldSize, size - oldSize);
+ }
+ // else no lines within the window have changed
+
+ } else if (Math.abs(shift) < size) {
+ if (shift < 0) {
+ // we can scroll
+ scroll(startLine, oldSize, shift);
+ // mark the lines at the end as new
+ for (int i = oldStartLine + oldSize; i < startLine + size; i++) {
+ markLineChanged(i);
+ }
+ } else {
+ // we cannot shift positive -- mark all changed
+ markLinesChanged(startLine, size);
+ }
+ } else {
+ // no scrolling possible
+ markLinesChanged(startLine, size);
+ }
+ }
+ }
+
+ @Override public boolean hasLineChanged(int line) {
+ if (line < getChangedLineCount()) {
+ return changedLines[line];
+ }
+ // since the height of the terminal could have changed but we have tracked only changes of the previous terminal
+ // height, any line outside the the range of the previous height has changed
+ return isInInterestWindow(line);
+ }
+
+ private int getChangedLineCount() {
+ return changedLines.length;
+ }
+
+ private void setChangedLine(int line, boolean changed) {
+ changedLines[line] = changed;
+ }
+
+ void setChangedLineCount(int length) {
+ changedLines = new boolean[length];
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/SynchronizedTerminalTextData.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/SynchronizedTerminalTextData.java
new file mode 100644
index 0000000..afea9c3
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/SynchronizedTerminalTextData.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse public synchronized License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Scharf (Wind River) - initial API and implementation
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+/**
+ * This is a decorator to make all access to an {@link ITerminalTextData} synchronized.
+ */
+public class SynchronizedTerminalTextData implements ITerminalTextData {
+ private final ITerminalTextData data;
+
+ public SynchronizedTerminalTextData(ITerminalTextData data) {
+ this.data = data;
+ }
+
+ @Override public synchronized void addLine() {
+ data.addLine();
+ }
+
+ @Override public synchronized void cleanLine(int line) {
+ data.cleanLine(line);
+ }
+
+ @Override public synchronized void copy(ITerminalTextData source) {
+ data.copy(source);
+ }
+
+ @Override public synchronized void copyLine(ITerminalTextData source, int sourceLine, int destinationLine) {
+ data.copyLine(source, sourceLine, destinationLine);
+ }
+
+ @Override public synchronized void copyRange(
+ ITerminalTextData source, int sourceStartLine, int destinationStartLine, int length) {
+ data.copyRange(source, sourceStartLine, destinationStartLine, length);
+ }
+
+ @Override public synchronized char getChar(int line, int column) {
+ return data.getChar(line, column);
+ }
+
+ @Override public synchronized char[] getChars(int line) {
+ return data.getChars(line);
+ }
+
+ @Override public synchronized int getCursorColumn() {
+ return data.getCursorColumn();
+ }
+
+ @Override public synchronized int getCursorLine() {
+ return data.getCursorLine();
+ }
+
+ @Override public synchronized int getHeight() {
+ return data.getHeight();
+ }
+
+ @Override public synchronized LineSegment[] getLineSegments(int line, int startColumn, int columnCount) {
+ return data.getLineSegments(line, startColumn, columnCount);
+ }
+
+ @Override public synchronized int getMaxHeight() {
+ return data.getMaxHeight();
+ }
+
+ @Override public synchronized Style getStyle(int line, int column) {
+ return data.getStyle(line, column);
+ }
+
+ @Override public synchronized Style[] getStyles(int line) {
+ return data.getStyles(line);
+ }
+
+ @Override public synchronized int getWidth() {
+ return data.getWidth();
+ }
+
+ @Override public synchronized ITerminalTextDataSnapshot makeSnapshot() {
+ return data.makeSnapshot();
+ }
+
+ @Override public synchronized void scroll(int startLine, int size, int shift) {
+ data.scroll(startLine, size, shift);
+ }
+
+ @Override public synchronized void setChar(int line, int column, char c, Style style) {
+ data.setChar(line, column, c, style);
+ }
+
+ @Override public synchronized void setChars(int line, int column, char[] chars, int start, int length, Style style) {
+ data.setChars(line, column, chars, start, length, style);
+ }
+
+ @Override public synchronized void setChars(int line, int column, char[] chars, Style style) {
+ data.setChars(line, column, chars, style);
+ }
+
+ @Override public synchronized void setCursorColumn(int column) {
+ data.setCursorColumn(column);
+ }
+
+ @Override public synchronized void setCursorLine(int line) {
+ data.setCursorLine(line);
+ }
+
+ @Override public synchronized void setDimensions(int height, int width) {
+ data.setDimensions(height, width);
+ }
+
+ @Override public synchronized void setMaxHeight(int height) {
+ data.setMaxHeight(height);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextData.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextData.java
new file mode 100644
index 0000000..70f2e5a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextData.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import java.util.*;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+public class TerminalTextData implements ITerminalTextData {
+ private final ITerminalTextData data;
+ private final List<TerminalTextDataSnapshot> snapshots = new ArrayList<TerminalTextDataSnapshot>();
+ private int cursorLine;
+ private int cursorColumn;
+
+ public TerminalTextData() {
+ this(new TerminalTextDataFastScroll());
+ }
+
+ public TerminalTextData(ITerminalTextData data) {
+ this.data = data;
+ }
+
+ @Override public int getWidth() {
+ return data.getWidth();
+ }
+
+ @Override public int getHeight() {
+ return data.getHeight();
+ }
+
+ @Override public void setDimensions(int height, int width) {
+ int currentHeight = getHeight();
+ int currentWidth = getWidth();
+ if (currentWidth == width && currentHeight == height) {
+ return;
+ }
+ data.setDimensions(height, width);
+ sendDimensionsChanged(currentHeight, currentWidth, height, width);
+ }
+
+ private void sendDimensionsChanged(int oldHeight, int oldWidth, int newHeight, int newWidth) {
+ // determine what has changed
+ if (oldWidth == newWidth) {
+ if (oldHeight < newHeight) {
+ sendLinesChangedToSnapshot(oldHeight, newHeight - oldHeight);
+ } else {
+ sendLinesChangedToSnapshot(newHeight, oldHeight - newHeight);
+ }
+ } else {
+ sendLinesChangedToSnapshot(0, oldHeight);
+ }
+ sendDimensionsChanged();
+ }
+
+ @Override public LineSegment[] getLineSegments(int line, int column, int len) {
+ return data.getLineSegments(line, column, len);
+ }
+
+ @Override public char getChar(int line, int column) {
+ return data.getChar(line, column);
+ }
+
+ @Override public Style getStyle(int line, int column) {
+ return data.getStyle(line, column);
+ }
+
+ @Override public void setChar(int line, int column, char c, Style style) {
+ data.setChar(line, column, c, style);
+ sendLineChangedToSnapshots(line);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, Style style) {
+ data.setChars(line, column, chars, style);
+ sendLineChangedToSnapshots(line);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, int start, int length, Style style) {
+ data.setChars(line, column, chars, start, length, style);
+ sendLineChangedToSnapshots(line);
+ }
+
+ @Override public void scroll(int startLine, int size, int shift) {
+ data.scroll(startLine, size, shift);
+ sendScrolledToSnapshots(startLine, size, shift);
+ }
+
+ @Override public String toString() {
+ return data.toString();
+ }
+
+ private void sendDimensionsChanged() {
+ for (TerminalTextDataSnapshot snapshot : snapshots) {
+ snapshot.markDimensionsChanged();
+ }
+ }
+
+ protected void sendLineChangedToSnapshots(int line) {
+ for (TerminalTextDataSnapshot snapshot : snapshots) {
+ snapshot.markLineChanged(line);
+ }
+ }
+
+ protected void sendLinesChangedToSnapshot(int startingLine, int lineCount) {
+ for (TerminalTextDataSnapshot snapshot : snapshots) {
+ snapshot.markLinesChanged(startingLine, lineCount);
+ }
+ }
+
+ /**
+ * Notifies snapshot that a region was scrolled.
+ * @param startingLine first line of scrolled region.
+ * @param lineCount size of scrolled region (number of lines.)
+ * @param shift delta by which the region is scrolled.
+ */
+ protected void sendScrolledToSnapshots(int startingLine, int lineCount, int shift) {
+ for (TerminalTextDataSnapshot snapshot : snapshots) {
+ snapshot.scroll(startingLine, lineCount, shift);
+ }
+ }
+
+ protected void sendCursorChanged() {
+ for (TerminalTextDataSnapshot snapshot : snapshots) {
+ snapshot.markCursorChanged();
+ }
+ }
+
+ /**
+ * Removes the snapshot from the observer list.
+ * @param snapshot a snapshot of a terminal model.
+ */
+ protected void removeSnapshot(TerminalTextDataSnapshot snapshot) {
+ snapshots.remove(snapshot);
+ }
+
+ @Override public ITerminalTextDataSnapshot makeSnapshot() {
+ TerminalTextDataSnapshot snapshot = new TerminalTextDataSnapshot(this);
+ snapshot.markDimensionsChanged();
+ snapshots.add(snapshot);
+ return snapshot;
+ }
+
+ @Override public void addLine() {
+ int oldHeight = getHeight();
+ data.addLine();
+ // was is an append or a scroll?
+ int newHeight = getHeight();
+ if (newHeight > oldHeight) {
+ // the line was appended
+ sendLinesChangedToSnapshot(oldHeight, 1);
+ int width = getWidth();
+ sendDimensionsChanged(oldHeight, width, newHeight, width);
+ } else {
+ // the line was scrolled
+ sendScrolledToSnapshots(0, oldHeight, -1);
+ }
+ }
+
+ @Override public void copy(ITerminalTextData source) {
+ data.copy(source);
+ cursorLine = source.getCursorLine();
+ cursorColumn = source.getCursorColumn();
+ }
+
+ @Override public void copyLine(ITerminalTextData source, int sourceLine, int destinationLine) {
+ data.copyLine(source, sourceLine, destinationLine);
+ }
+
+ @Override public void copyRange(ITerminalTextData source, int sourceStartLine, int destinationStartLine, int length) {
+ data.copyRange(source, sourceStartLine, destinationStartLine, length);
+ }
+
+ @Override public char[] getChars(int line) {
+ return data.getChars(line);
+ }
+
+ @Override public Style[] getStyles(int line) {
+ return data.getStyles(line);
+ }
+
+ @Override public int getMaxHeight() {
+ return data.getMaxHeight();
+ }
+
+ @Override public void setMaxHeight(int height) {
+ data.setMaxHeight(height);
+ }
+
+ @Override public void cleanLine(int line) {
+ data.cleanLine(line);
+ sendLineChangedToSnapshots(line);
+ }
+
+ @Override public int getCursorColumn() {
+ return cursorColumn;
+ }
+
+ @Override public int getCursorLine() {
+ return cursorLine;
+ }
+
+ @Override public void setCursorColumn(int column) {
+ cursorColumn = column;
+ sendCursorChanged();
+ }
+
+ @Override public void setCursorLine(int line) {
+ cursorLine = line;
+ sendCursorChanged();
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataFastScroll.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataFastScroll.java
new file mode 100644
index 0000000..46acdd2
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataFastScroll.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import org.eclipse.core.runtime.Assert;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+/**
+ * This class is optimized for scrolling the entire {@link #getHeight()}. The scrolling is done by moving an offset into
+ * the data and using the modulo operator.
+ */
+public class TerminalTextDataFastScroll implements ITerminalTextData {
+ private final ITerminalTextData data;
+ private int height;
+ private int maxHeight;
+ private int offset;
+
+ public TerminalTextDataFastScroll(ITerminalTextData data, int maxHeight) {
+ this.maxHeight = maxHeight;
+ this.data = data;
+ this.data.setDimensions(this.maxHeight, this.data.getWidth());
+ if (this.maxHeight > 2) {
+ moveOffset(-2);
+ }
+ }
+
+ public TerminalTextDataFastScroll(int maxHeight) {
+ this(new TerminalTextDataStore(), maxHeight);
+ }
+
+ public TerminalTextDataFastScroll() {
+ this(new TerminalTextDataStore(), 1);
+ }
+
+ private int getPositionOfLine(int line) {
+ return (line + offset) % maxHeight;
+ }
+
+ private void moveOffset(int delta) {
+ Assert.isTrue(Math.abs(delta) < maxHeight);
+ offset = (maxHeight + offset + delta) % maxHeight;
+ }
+
+ @Override public void addLine() {
+ if (getHeight() < maxHeight) {
+ setDimensions(getHeight() + 1, getWidth());
+ } else {
+ scroll(0, getHeight(), -1);
+ }
+ }
+
+ @Override public void cleanLine(int line) {
+ data.cleanLine(getPositionOfLine(line));
+ }
+
+ @Override public void copy(ITerminalTextData source) {
+ int height = source.getHeight();
+ setDimensions(source.getHeight(), source.getWidth());
+ for (int i = 0; i < height; i++) {
+ data.copyLine(source, i, getPositionOfLine(i));
+ }
+ }
+
+ @Override public void copyLine(ITerminalTextData source, int sourceLine, int destinationLine) {
+ data.copyLine(source, sourceLine, getPositionOfLine(destinationLine));
+ }
+
+ @Override public void copyRange(ITerminalTextData source, int sourceStartLine, int destinationStartLine, int length) {
+ Assert.isTrue(destinationStartLine >= 0 && destinationStartLine + length <= height);
+ for (int i = 0; i < length; i++) {
+ data.copyLine(source, i + sourceStartLine, getPositionOfLine(i + destinationStartLine));
+ }
+ }
+
+ @Override public char getChar(int line, int column) {
+ Assert.isTrue(line >= 0 && line < height);
+ return data.getChar(getPositionOfLine(line), column);
+ }
+
+ @Override public char[] getChars(int line) {
+ Assert.isTrue(line >= 0 && line < height);
+ return data.getChars(getPositionOfLine(line));
+ }
+
+ @Override public int getHeight() {
+ return height;
+ }
+
+ @Override public LineSegment[] getLineSegments(int line, int startCol, int numberOfCols) {
+ Assert.isTrue(line >= 0 && line < height);
+ return data.getLineSegments(getPositionOfLine(line), startCol, numberOfCols);
+ }
+
+ @Override public int getMaxHeight() {
+ return maxHeight;
+ }
+
+ @Override public Style getStyle(int line, int column) {
+ Assert.isTrue(line >= 0 && line < height);
+ return data.getStyle(getPositionOfLine(line), column);
+ }
+
+ @Override public Style[] getStyles(int line) {
+ Assert.isTrue(line >= 0 && line < height);
+ return data.getStyles(getPositionOfLine(line));
+ }
+
+ @Override public int getWidth() {
+ return data.getWidth();
+ }
+
+ @Override public ITerminalTextDataSnapshot makeSnapshot() {
+ return data.makeSnapshot();
+ }
+
+ private void cleanLines(int line, int len) {
+ for (int i = line; i < line + len; i++) {
+ data.cleanLine(getPositionOfLine(i));
+ }
+ }
+
+ @Override public void scroll(int startLine, int size, int shift) {
+ Assert.isTrue(startLine >= 0 && startLine + size <= height);
+ if (shift >= maxHeight || -shift >= maxHeight) {
+ cleanLines(startLine, maxHeight - startLine);
+ return;
+ }
+ if (size == height) {
+ // This is the case this class is optimized for!
+ moveOffset(-shift);
+ // We only have to clean the lines that appear by the move.
+ if (shift < 0) {
+ cleanLines(Math.max(startLine, startLine + size + shift), Math.min(-shift, getHeight() - startLine));
+ } else {
+ cleanLines(startLine, Math.min(shift, getHeight() - startLine));
+ }
+ } else {
+ // we have to copy the lines.
+ if (shift < 0) {
+ // move the region up
+ for (int i = startLine; i < startLine + size + shift; i++) {
+ data.copyLine(data, getPositionOfLine(i - shift), getPositionOfLine(i));
+ }
+ // then clean the opened lines
+ cleanLines(Math.max(0, startLine + size + shift), Math.min(-shift, getHeight() - startLine));
+ } else {
+ for (int i = startLine + size - 1; i >= startLine && i - shift >= 0; i--) {
+ data.copyLine(data, getPositionOfLine(i - shift), getPositionOfLine(i));
+ }
+ cleanLines(startLine, Math.min(shift, getHeight() - startLine));
+ }
+ }
+ }
+
+ @Override public void setChar(int line, int column, char c, Style style) {
+ Assert.isTrue(line >= 0 && line < height);
+ data.setChar(getPositionOfLine(line), column, c, style);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
+ Assert.isTrue(line >= 0 && line < height);
+ data.setChars(getPositionOfLine(line), column, chars, start, len, style);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, Style style) {
+ Assert.isTrue(line >= 0 && line < height);
+ data.setChars(getPositionOfLine(line), column, chars, style);
+ }
+
+ @Override public void setDimensions(int height, int width) {
+ Assert.isTrue(height >= 0 && width >= 0);
+ if (height > maxHeight) {
+ setMaxHeight(height);
+ }
+ this.height = height;
+ if (width != data.getWidth()) {
+ data.setDimensions(maxHeight, width);
+ }
+ }
+
+ @Override public void setMaxHeight(int maxHeight) {
+ Assert.isTrue(maxHeight >= height);
+ // move everything to offset0
+ int start = getPositionOfLine(0);
+ if (start != 0) {
+ // invent a more efficient algorithm....
+ ITerminalTextData buffer = new TerminalTextDataStore();
+ // create a buffer with the expected height
+ buffer.setDimensions(maxHeight, getWidth());
+ int n = Math.min(maxHeight - start, maxHeight);
+ // copy the first part
+ buffer.copyRange(data, start, 0, n);
+ // copy the second part
+ if (n < maxHeight) {
+ buffer.copyRange(data, 0, n, Math.min(maxHeight - n, maxHeight - n));
+ }
+ // copy the buffer back to our data
+ data.copy(buffer);
+ moveOffset(-start);
+ } else {
+ data.setDimensions(maxHeight, data.getWidth());
+ }
+ this.maxHeight = maxHeight;
+ }
+
+ @Override public int getCursorColumn() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public int getCursorLine() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void setCursorColumn(int column) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void setCursorLine(int line) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataSnapshot.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataSnapshot.java
new file mode 100644
index 0000000..aed2273
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataSnapshot.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.Assert;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+class TerminalTextDataSnapshot implements ITerminalTextDataSnapshot {
+ // The changes of the current snapshot relative to the previous snapshot.
+ private volatile ISnapshotChanges currentChanges;
+
+ // Keeps track of changes that happened since the current snapshot has been made.
+ private ISnapshotChanges futureChanges;
+
+ // Is used as lock and is the reference to the terminal we take snapshots from.
+ private final TerminalTextData terminal;
+
+ // A snapshot copy of terminal. It does not need internal synchronization.
+ private final TerminalTextDataWindow snapshot;
+
+ private final List<SnapshotOutOfDateListener> listeners = new ArrayList<SnapshotOutOfDateListener>();
+
+ private boolean listenersNeedNotify;
+ private int interestWindowSize;
+ private int interestWindowStartLine;
+
+ TerminalTextDataSnapshot(TerminalTextData terminal) {
+ snapshot = new TerminalTextDataWindow();
+ this.terminal = terminal;
+ currentChanges = new SnapshotChanges(this.terminal.getHeight());
+ currentChanges.setTerminalChanged();
+ futureChanges = new SnapshotChanges(this.terminal.getHeight());
+ futureChanges.markLinesChanged(0, this.terminal.getHeight());
+ listenersNeedNotify = true;
+ interestWindowSize = -1;
+ }
+
+ @Override public void detach() {
+ terminal.removeSnapshot(this);
+ }
+
+ @Override public boolean isOutOfDate() {
+ // This is called from terminal, therefore we lock on terminal
+ synchronized (terminal) {
+ return futureChanges.hasChanged();
+ }
+ }
+
+ @Override public void updateSnapshot(boolean detectScrolling) {
+ // Make sure terminal does not change while we make the snapshot.
+ synchronized (terminal) {
+ // let's make the future changes current
+ currentChanges = futureChanges;
+ futureChanges = new SnapshotChanges(terminal.getHeight());
+ futureChanges.setInterestWindow(interestWindowStartLine, interestWindowSize);
+ // and update the snapshot
+ if (snapshot.getHeight() != terminal.getHeight() || snapshot.getWidth() != terminal.getWidth()) {
+ if (interestWindowSize == -1) {
+ snapshot.setWindow(0, terminal.getHeight());
+ }
+ // if the dimensions have changed, we need a full copy.
+ snapshot.copy(terminal);
+ // and we mark all lines as changed.
+ currentChanges.setAllChanged(terminal.getHeight());
+ } else {
+ // first we do the scroll on the copy
+ int start = currentChanges.getScrollWindowStartLine();
+ int lines = Math.min(currentChanges.getScrollWindowSize(), snapshot.getHeight() - start);
+ snapshot.scroll(start, lines, currentChanges.getScrollWindowShift());
+ // and then create the snapshot of the changed lines.
+ currentChanges.copyChangedLines(snapshot, terminal);
+ }
+ listenersNeedNotify = true;
+ snapshot.setCursorLine(terminal.getCursorLine());
+ snapshot.setCursorColumn(terminal.getCursorColumn());
+ }
+ if (!detectScrolling) {
+ // let's pretend there was no scrolling and convert the scrolling into line changes
+ currentChanges.convertScrollingIntoChanges();
+ }
+ }
+
+ @Override public char getChar(int line, int column) {
+ return snapshot.getChar(line, column);
+ }
+
+ @Override public int getHeight() {
+ return snapshot.getHeight();
+ }
+
+ @Override public LineSegment[] getLineSegments(int line, int column, int len) {
+ return snapshot.getLineSegments(line, column, len);
+ }
+
+ @Override public Style getStyle(int line, int column) {
+ return snapshot.getStyle(line, column);
+ }
+
+ @Override public int getWidth() {
+ return snapshot.getWidth();
+ }
+
+ @Override public int getFirstChangedLine() {
+ return currentChanges.getFirstChangedLine();
+ }
+
+ @Override public int getLastChangedLine() {
+ return currentChanges.getLastChangedLine();
+ }
+
+ @Override public boolean hasLineChanged(int line) {
+ return currentChanges.hasLineChanged(line);
+ }
+
+ @Override public boolean hasDimensionsChanged() {
+ return currentChanges.hasDimensionsChanged();
+ }
+
+ @Override public boolean hasTerminalChanged() {
+ return currentChanges.hasTerminalChanged();
+ }
+
+ @Override public int getScrollWindowStartLine() {
+ return currentChanges.getScrollWindowStartLine();
+ }
+
+ @Override public int getScrollWindowSize() {
+ return currentChanges.getScrollWindowSize();
+ }
+
+ @Override public int getScrollWindowShift() {
+ return currentChanges.getScrollWindowShift();
+ }
+
+ void markLineChanged(int line) {
+ futureChanges.markLineChanged(line);
+ futureChanges.setTerminalChanged();
+ notifyListers();
+ }
+
+ void markLinesChanged(int line, int size) {
+ futureChanges.markLinesChanged(line, size);
+ futureChanges.setTerminalChanged();
+ notifyListers();
+ }
+
+ void markDimensionsChanged() {
+ futureChanges.markDimensionsChanged();
+ futureChanges.setTerminalChanged();
+ notifyListers();
+ }
+
+ void markCursorChanged() {
+ futureChanges.markCursorChanged();
+ futureChanges.setTerminalChanged();
+ notifyListers();
+ }
+
+ void scroll(int startLine, int size, int shift) {
+ futureChanges.scroll(startLine, size, shift);
+ futureChanges.setTerminalChanged();
+ notifyListers();
+ }
+
+ private void notifyListers() {
+ synchronized (terminal) {
+ if (listenersNeedNotify) {
+ for (SnapshotOutOfDateListener listener : listeners) {
+ listener.snapshotOutOfDate(this);
+ }
+ listenersNeedNotify = false;
+ }
+ }
+ }
+
+ @Override public ITerminalTextDataSnapshot makeSnapshot() {
+ return snapshot.makeSnapshot();
+ }
+
+ @Override synchronized public void addListener(SnapshotOutOfDateListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override synchronized public void removeListener(SnapshotOutOfDateListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override public String toString() {
+ return snapshot.toString();
+ }
+
+ @Override public int getInterestWindowSize() {
+ return interestWindowSize;
+ }
+
+ @Override public int getInterestWindowStartLine() {
+ return interestWindowStartLine;
+ }
+
+ @Override public void setInterestWindow(int startLine, int size) {
+ Assert.isTrue(startLine >= 0 && size >= 0);
+ interestWindowStartLine = startLine;
+ interestWindowSize = size;
+ snapshot.setWindow(startLine, size);
+ futureChanges.setInterestWindow(startLine, size);
+ notifyListers();
+ }
+
+ @Override public char[] getChars(int line) {
+ return snapshot.getChars(line);
+ }
+
+ @Override public Style[] getStyles(int line) {
+ return snapshot.getStyles(line);
+ }
+
+ @Override public int getCursorColumn() {
+ return snapshot.getCursorColumn();
+ }
+
+ @Override public int getCursorLine() {
+ return snapshot.getCursorLine();
+ }
+
+ @Override public ITerminalTextData getTerminalTextData() {
+ return terminal;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataStore.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataStore.java
new file mode 100644
index 0000000..95cd53c
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataStore.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import static java.util.Arrays.copyOf;
+
+import java.lang.reflect.Array;
+import java.util.*;
+
+import org.eclipse.core.runtime.Assert;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+public class TerminalTextDataStore implements ITerminalTextData {
+ private char[][] chars;
+ private Style[][] styles;
+ private int width;
+ private int height;
+ private int maxHeight;
+ private int cursorColumn;
+ private int cursorLine;
+
+ public TerminalTextDataStore() {
+ chars = new char[0][];
+ styles = new Style[0][];
+ width = 0;
+ }
+
+ @Override public int getWidth() {
+ return width;
+ }
+
+ @Override public int getHeight() {
+ return height;
+ }
+
+ @Override public void setDimensions(int height, int width) {
+ Assert.isTrue(height >= 0 && width >= 0);
+ // Just extend the region.
+ if (height > chars.length) {
+ int h = 4 * height / 3;
+ if (maxHeight > 0 && h > maxHeight) {
+ h = maxHeight;
+ }
+ styles = (Style[][]) resizeArray(styles, height);
+ chars = (char[][]) resizeArray(chars, height);
+ }
+ // Clean the new lines
+ if (height > this.height) {
+ for (int i = this.height; i < height; i++) {
+ styles[i] = null;
+ chars[i] = null;
+ }
+ }
+ // Set dimensions after successful resize.
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Reallocates an array with a new size, and copies the contents of the old array to the new array.
+ *
+ * @param originalArray the old array, to be reallocated.
+ * @param newSize the new array size.
+ * @return A new array with the same contents (chopped off if needed or filled with 0 or null).
+ */
+ private Object resizeArray(Object originalArray, int newSize) {
+ int oldSize = Array.getLength(originalArray);
+ if (oldSize == newSize) {
+ return originalArray;
+ }
+ Class<?> elementType = originalArray.getClass().getComponentType();
+ Object newArray = Array.newInstance(elementType, newSize);
+ int preserveLength = Math.min(oldSize, newSize);
+ if (preserveLength > 0) {
+ System.arraycopy(originalArray, 0, newArray, 0, preserveLength);
+ }
+ return newArray;
+ }
+
+ @Override public LineSegment[] getLineSegments(int line, int startingColumn, int columnCount) {
+ // get the styles and chars for this line
+ Style[] styles = this.styles[line];
+ char[] chars = this.chars[line];
+ int column = startingColumn;
+ int size = startingColumn + columnCount;
+ // Expand the line if needed
+ if (styles == null) {
+ styles = new Style[size];
+ } else if (styles.length < size) {
+ styles = (Style[]) resizeArray(styles, size);
+ }
+ if (chars == null) {
+ chars = new char[size];
+ } else if (chars.length < size) {
+ chars = (char[]) resizeArray(chars, size);
+ }
+ // Create the line segments
+ Style style = styles[startingColumn];
+ List<LineSegment> segments = new ArrayList<LineSegment>();
+ for (int i = startingColumn; i < size; i++) {
+ if (styles[i] != style) {
+ segments.add(new LineSegment(column, new String(chars, column, i - column), style));
+ style = styles[i];
+ column = i;
+ }
+ }
+ if (column < size) {
+ segments.add(new LineSegment(column, new String(chars, column, size - column), style));
+ }
+ return segments.toArray(new LineSegment[segments.size()]);
+ }
+
+ @Override public char getChar(int line, int column) {
+ Assert.isTrue(column < width);
+ if (chars[line] == null || column >= chars[line].length) {
+ return 0;
+ }
+ return chars[line][column];
+ }
+
+ @Override public Style getStyle(int line, int column) {
+ Assert.isTrue(column < width);
+ if (styles[line] == null || column >= styles[line].length) {
+ return null;
+ }
+ return styles[line][column];
+ }
+
+ void ensureLineLength(int iLine, int length) {
+ if (length > width) {
+ throw new RuntimeException();
+ }
+ if (chars[iLine] == null) {
+ chars[iLine] = new char[length];
+ } else if (chars[iLine].length < length) {
+ chars[iLine] = (char[]) resizeArray(chars[iLine], length);
+ }
+ if (styles[iLine] == null) {
+ styles[iLine] = new Style[length];
+ } else if (styles[iLine].length < length) {
+ styles[iLine] = (Style[]) resizeArray(styles[iLine], length);
+ }
+ }
+
+ @Override public void setChar(int line, int column, char c, Style style) {
+ ensureLineLength(line, column + 1);
+ chars[line][column] = c;
+ styles[line][column] = style;
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, Style style) {
+ setChars(line, column, chars, 0, chars.length, style);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
+ ensureLineLength(line, column + len);
+ for (int i = 0; i < len; i++) {
+ this.chars[line][column + i] = chars[i + start];
+ this.styles[line][column + i] = style;
+ }
+ }
+
+ @Override public void scroll(int startLine, int size, int shift) {
+ Assert.isTrue(startLine + size <= getHeight());
+ if (shift < 0) {
+ // move the region up
+ for (int i = startLine; i < startLine + size + shift; i++) {
+ chars[i] = chars[i - shift];
+ styles[i] = styles[i - shift];
+ }
+ // then clean the opened lines
+ cleanLines(Math.max(startLine, startLine + size + shift), Math.min(-shift, getHeight() - startLine));
+ } else {
+ for (int i = startLine + size - 1; i >= startLine && i - shift >= 0; i--) {
+ chars[i] = chars[i - shift];
+ styles[i] = styles[i - shift];
+ }
+ cleanLines(startLine, Math.min(shift, getHeight() - startLine));
+ }
+ }
+
+ private void cleanLines(int line, int len) {
+ for (int i = line; i < line + len; i++) {
+ chars[i] = null;
+ styles[i] = null;
+ }
+ }
+
+ @Override public String toString() {
+ StringBuffer buff = new StringBuffer();
+ for (int line = 0; line < getHeight(); line++) {
+ if (line > 0) {
+ buff.append("\n");
+ }
+ for (int column = 0; column < width; column++) {
+ buff.append(getChar(line, column));
+ }
+ }
+ return buff.toString();
+ }
+
+ @Override public ITerminalTextDataSnapshot makeSnapshot() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void addLine() {
+ if (maxHeight > 0 && getHeight() < maxHeight) {
+ setDimensions(getHeight() + 1, getWidth());
+ } else {
+ scroll(0, getHeight(), -1);
+ }
+ }
+
+ @Override public void copy(ITerminalTextData source) {
+ width = source.getWidth();
+ int newHeight = source.getHeight();
+ if (getHeight() != newHeight) {
+ chars = new char[newHeight][];
+ styles = new Style[newHeight][];
+ }
+ for (int i = 0; i < newHeight; i++) {
+ chars[i] = source.getChars(i);
+ styles[i] = source.getStyles(i);
+ }
+ height = newHeight;
+ cursorLine = source.getCursorLine();
+ cursorColumn = source.getCursorColumn();
+ }
+
+ @Override public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine, int length) {
+ for (int i = 0; i < length; i++) {
+ chars[i + destStartLine] = source.getChars(i + sourceStartLine);
+ styles[i + destStartLine] = source.getStyles(i + sourceStartLine);
+ }
+ }
+
+ @Override public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
+ chars[destLine] = source.getChars(sourceLine);
+ styles[destLine] = source.getStyles(sourceLine);
+ }
+
+ @Override public char[] getChars(int line) {
+ if (chars[line] == null) {
+ return null;
+ }
+ return chars[line].clone();
+ }
+
+ @Override public Style[] getStyles(int line) {
+ if (styles[line] == null) {
+ return null;
+ }
+ return styles[line].clone();
+ }
+
+ public void setLine(int line, char[] chars, Style[] styles) {
+ this.chars[line] = copyOf(chars, chars.length);
+ this.styles[line] = copyOf(styles, styles.length);
+ }
+
+ @Override public void setMaxHeight(int height) {
+ maxHeight = height;
+ }
+
+ @Override public int getMaxHeight() {
+ return maxHeight;
+ }
+
+ @Override public void cleanLine(int line) {
+ chars[line] = null;
+ styles[line] = null;
+ }
+
+ @Override public int getCursorColumn() {
+ return cursorColumn;
+ }
+
+ @Override public int getCursorLine() {
+ return cursorLine;
+ }
+
+ @Override public void setCursorColumn(int column) {
+ cursorColumn = column;
+ }
+
+ @Override public void setCursorLine(int line) {
+ cursorLine = line;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataWindow.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataWindow.java
new file mode 100644
index 0000000..299fa67
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/model/TerminalTextDataWindow.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.model;
+
+import org.eclipse.core.runtime.Assert;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+/**
+ * This class stores the data only within a window {@link #setWindow(int, int)} and {@link #getWindowStartLine()} and
+ * {@link #getWindowSize()}. Everything outside the is {@code char=='\000'} and {@code style=null}.
+ */
+public class TerminalTextDataWindow implements ITerminalTextData {
+ private final ITerminalTextData data;
+
+ private int windowStartLine;
+ private int windowSize;
+ private int height;
+ private int maxHeight;
+
+ public TerminalTextDataWindow(ITerminalTextData data) {
+ this.data = data;
+ }
+
+ public TerminalTextDataWindow() {
+ this(new TerminalTextDataStore());
+ }
+
+ private boolean isInWindow(int line) {
+ return line >= windowStartLine && line < windowStartLine + windowSize;
+ }
+
+ @Override public char getChar(int line, int column) {
+ if (!isInWindow(line)) {
+ return 0;
+ }
+ return data.getChar(line - windowStartLine, column);
+ }
+
+ @Override public char[] getChars(int line) {
+ if (!isInWindow(line)) {
+ return null;
+ }
+ return data.getChars(line - windowStartLine);
+ }
+
+ @Override public int getHeight() {
+ return height;
+ }
+
+ @Override public LineSegment[] getLineSegments(int line, int startingColumn, int columnCount) {
+ if (!isInWindow(line)) {
+ return new LineSegment[] { new LineSegment(startingColumn, new String(new char[columnCount]), null) };
+ }
+ return data.getLineSegments(line - windowStartLine, startingColumn, columnCount);
+ }
+
+ @Override public int getMaxHeight() {
+ return maxHeight;
+ }
+
+ @Override public Style getStyle(int line, int column) {
+ if (!isInWindow(line)) {
+ return null;
+ }
+ return data.getStyle(line - windowStartLine, column);
+ }
+
+ @Override public Style[] getStyles(int line) {
+ if (!isInWindow(line)) {
+ return null;
+ }
+ return data.getStyles(line - windowStartLine);
+ }
+
+ @Override public int getWidth() {
+ return data.getWidth();
+ }
+
+ @Override public ITerminalTextDataSnapshot makeSnapshot() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void addLine() {
+ if (maxHeight > 0 && getHeight() < maxHeight) {
+ setDimensions(getHeight() + 1, getWidth());
+ } else {
+ scroll(0, getHeight(), -1);
+ }
+ }
+
+ @Override public void copy(ITerminalTextData source) {
+ // We inherit the dimensions of the source.
+ setDimensions(source.getHeight(), source.getWidth());
+ int n = Math.min(windowSize, source.getHeight() - windowStartLine);
+ if (n > 0) {
+ data.copyRange(source, windowStartLine, 0, n);
+ }
+ }
+
+ @Override public void copyRange(ITerminalTextData source, int sourceStartLine, int destinationStartLine, int length) {
+ int newLength = length;
+ int destinationStart = destinationStartLine - windowStartLine;
+ int sourceStart = sourceStartLine;
+ // If start outside our range, cut the length to copy.
+ if (destinationStart < 0) {
+ newLength += destinationStart;
+ sourceStart -= destinationStart;
+ destinationStart = 0;
+ }
+ // Do not exceed the window size.
+ newLength = Math.min(newLength, windowSize);
+ if (newLength > 0) {
+ data.copyRange(source, sourceStart, destinationStart, newLength);
+ }
+ }
+
+ @Override public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
+ if (isInWindow(destLine)) {
+ data.copyLine(source, sourceLine, destLine - windowStartLine);
+ }
+ }
+
+ @Override public void scroll(int startLine, int lineCount, int shift) {
+ Assert.isTrue(startLine >= 0 && startLine + lineCount <= height);
+ int length = lineCount;
+ int start = startLine - windowStartLine;
+ // If start outside our range, cut the length to copy.
+ if (start < 0) {
+ length += start;
+ start = 0;
+ }
+ length = Math.min(length, windowSize - start);
+ // do not exceed the window size
+ if (length > 0) {
+ data.scroll(start, length, shift);
+ }
+ }
+
+ @Override public void setChar(int line, int column, char c, Style style) {
+ if (!isInWindow(line)) {
+ return;
+ }
+ data.setChar(line - windowStartLine, column, c, style);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
+ if (!isInWindow(line)) {
+ return;
+ }
+ data.setChars(line - windowStartLine, column, chars, start, len, style);
+ }
+
+ @Override public void setChars(int line, int column, char[] chars, Style style) {
+ if (!isInWindow(line)) {
+ return;
+ }
+ data.setChars(line - windowStartLine, column, chars, style);
+ }
+
+ @Override public void setDimensions(int height, int width) {
+ Assert.isTrue(height >= 0);
+ data.setDimensions(windowSize, width);
+ setHeight(height);
+ }
+
+ @Override public void setMaxHeight(int maxHeight) {
+ this.maxHeight = maxHeight;
+ }
+
+ public void setWindow(int startLine, int size) {
+ windowStartLine = startLine;
+ windowSize = size;
+ data.setDimensions(windowSize, getWidth());
+ }
+
+ public int getWindowStartLine() {
+ return windowStartLine;
+ }
+
+ public int getWindowSize() {
+ return windowSize;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ @Override public void cleanLine(int line) {
+ if (isInWindow(line)) {
+ data.cleanLine(line - windowStartLine);
+ }
+ }
+
+ @Override public int getCursorColumn() {
+ return data.getCursorColumn();
+ }
+
+ @Override public int getCursorLine() {
+ return data.getCursorLine();
+ }
+
+ @Override public void setCursorColumn(int column) {
+ data.setCursorColumn(column);
+ }
+
+ @Override public void setCursorLine(int line) {
+ data.setCursorLine(line);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java
new file mode 100644
index 0000000..f35ce93
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.provisional.api;
+
+import java.io.OutputStream;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+/**
+ * A connection type.
+ *
+ * @author Michael Scharf
+ */
+public interface ITerminalConnector extends IAdaptable {
+ String getId();
+
+ String getName();
+
+ boolean isInitialized();
+
+ String getInitializationErrorMessage();
+
+ void connect(ITerminalControl control);
+
+ void disconnect();
+
+ boolean isLocalEcho();
+
+ void setTerminalSize(int newWidth, int newHeight);
+
+ OutputStream getTerminalToRemoteStream();
+
+ String getSettingsSummary();
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java
new file mode 100644
index 0000000..ab0cc0f
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.provisional.api;
+
+import java.io.*;
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Represents the terminal view as seen by a terminal connection.
+ *
+ * @author Michael Scharf
+ */
+public interface ITerminalControl {
+ TerminalState getState();
+
+ void setState(TerminalState state);
+
+ void setUpTerminal(Composite parent);
+
+ Shell getShell();
+
+ /**
+ * Set the encoding that the terminal uses to decode bytes from the Terminal-to-remote-Stream into Unicode characters
+ * used in Java; or, to encode characters typed by the user into bytes sent over the wire to the remote.
+ * <p>
+ * By default, the local platform default encoding is used. Also note that the encoding must not be applied in case
+ * the terminal stream is processed by some data transfer protocol which requires binary data.
+ * </p>
+ * <p>
+ * Validity of the encoding set here is not checked. Since some encodings do not cover the entire range of Unicode
+ * characters, it can happen that a particular Unicode text typed in by the user can not be encoded into a byte stream
+ * with the encoding specified. and {@link UnsupportedEncodingException} will be thrown in this case at the time the
+ * text is about to be processed.
+ * </p>
+ * <p>
+ * The concrete encoding to use can either be specified manually by a user, by means of a dialog, or a connector can
+ * try to obtain it automatically from the remote side (e.g. by evaluating an environment variable such as LANG on
+ * UNIX systems.)
+ * </p>
+ *
+ * @param encoding the new encoding.
+ * @throws UnsupportedEncodingException if the given encoding is not supported.
+ */
+ void setEncoding(String encoding) throws UnsupportedEncodingException;
+
+ String getEncoding();
+
+ /**
+ * Show a text in the terminal. If puts newlines at the beginning and the end.
+ *
+ * @param text the text to display.
+ */
+ void displayTextInTerminal(String text);
+
+ /**
+ * Returns the stream used to write to the terminal. Any bytes written to this stream appear in the terminal or are
+ * interpreted by the emulator as control sequences. The stream in the opposite direction, terminal to remote is in
+ * {@link ITerminalConnector#getTerminalToRemoteStream()}.
+ *
+ * @return the stream used to write to the terminal.
+ */
+ OutputStream getRemoteToTerminalOutputStream();
+
+ void setTerminalTitle(String title);
+
+ /**
+ * Show an error message during connect.
+ * @param errorMessage the new error message.
+ */
+ // TODO(Michael Scharf): Should be replaced by a better error notification mechanism!
+ void setErrorMessage(String errorMessage);
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/Logger.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/Logger.java
new file mode 100644
index 0000000..e1142e7
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/Logger.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.provisional.api;
+
+import static org.eclipse.core.runtime.IStatus.*;
+
+import java.io.*;
+
+import org.eclipse.core.runtime.Status;
+
+import com.google.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
+
+/**
+ * A simple logger class. Every method in this class is static, so they can be called from both class and instance
+ * methods. To use this class, write code like this:
+ * <p>
+ *
+ * <pre>
+ * Logger.log("something has happened");
+ * Logger.log("counter is " + counter);
+ * </pre>
+ *
+ * @author Fran Litterio <francis.litterio@windriver.com>
+ */
+public final class Logger {
+ public static final String TRACE_DEBUG_LOG = "org.eclipse.tm.terminal/debug/log";
+ public static final String TRACE_DEBUG_LOG_ERROR = "org.eclipse.tm.terminal/debug/log/error";
+ public static final String TRACE_DEBUG_LOG_INFO = "org.eclipse.tm.terminal/debug/log/info";
+ public static final String TRACE_DEBUG_LOG_CHAR = "org.eclipse.tm.terminal/debug/log/char";
+ public static final String TRACE_DEBUG_LOG_BUFFER_SIZE = "org.eclipse.tm.terminal/debug/log/buffer/size";
+
+ private static PrintStream logStream;
+
+ static {
+ String logFile = logFile();
+ if (logFile != null) {
+ try {
+ logStream = new PrintStream(new FileOutputStream(logFile, true));
+ } catch (Exception ex) {
+ logStream = System.err;
+ logStream.println("Exception when opening log file -- logging to stderr!");
+ ex.printStackTrace(logStream);
+ }
+ }
+ }
+
+ private static String logFile() {
+ File directory = new File("C:\\eclipselogs");
+ if (directory.isDirectory()) {
+ return directory + "\\tmterminal.log";
+ }
+ directory = new File("/tmp/eclipselogs");
+ if (directory.isDirectory()) {
+ return directory + "/tmterminal.log";
+ }
+ return null;
+ }
+
+ /**
+ * Encodes text such that non-printable control characters are converted into user-readable escape sequences for
+ * logging.
+ * @param message the text to encode
+ * @return encoded the encoded text;
+ */
+ public static final String encode(String message) {
+ boolean encoded = false;
+ StringBuilder buffer = new StringBuilder(message.length() + 32);
+ for (int i = 0; i < message.length(); i++) {
+ char c = message.charAt(i);
+ switch (c) {
+ case '\\':
+ case '\'':
+ buffer.append('\\').append(c);
+ encoded = true;
+ break;
+ case '\r':
+ buffer.append('\\').append('r');
+ encoded = true;
+ break;
+ case '\n':
+ buffer.append('\\').append('n');
+ encoded = true;
+ break;
+ case '\t':
+ buffer.append('\\').append('t');
+ encoded = true;
+ break;
+ case '\f':
+ buffer.append('\\').append('f');
+ encoded = true;
+ break;
+ case '\b':
+ buffer.append('\\').append('b');
+ encoded = true;
+ break;
+ default:
+ if (c <= '\u000f') {
+ buffer.append('\\').append('x').append('0').append(Integer.toHexString(c));
+ encoded = true;
+ } else if (c >= ' ' && c < '\u007f') {
+ buffer.append(c);
+ } else if (c <= '\u00ff') {
+ buffer.append('\\').append('x').append(Integer.toHexString(c));
+ encoded = true;
+ } else {
+ buffer.append('\\').append('u');
+ if (c <= '\u0fff') {
+ buffer.append('0');
+ }
+ buffer.append(Integer.toHexString(c));
+ encoded = true;
+ }
+ }
+ }
+ if (encoded) {
+ return buffer.toString();
+ }
+ return message;
+ }
+
+ public static final boolean isLogEnabled() {
+ return (logStream != null);
+ }
+
+ public static final void log(String message) {
+ if (logStream != null) {
+ StackTraceElement caller = Thread.currentThread().getStackTrace()[1];
+ String className = caller.getClassName();
+ className = className.substring(className.lastIndexOf('.') + 1);
+ logStream.println(className + "." + caller.getMethodName() + ":" + caller.getLineNumber() + ": " + message);
+ logStream.flush();
+ }
+ }
+
+ public static final void logException(Exception e) {
+ if (TerminalPlugin.getDefault() != null) {
+ TerminalPlugin.getDefault().getLog().log(new Status(ERROR, TerminalPlugin.PLUGIN_ID, OK, e.getMessage(), e));
+ } else {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/TerminalState.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/TerminalState.java
new file mode 100644
index 0000000..384d05a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/TerminalState.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.provisional.api;
+
+/**
+ * Represent the sate of a terminal connection.
+ *
+ * @author Michael Scharf
+ */
+public enum TerminalState {
+ /**
+ * The terminal is not connected.
+ */
+ CLOSED("CLOSED"), CONNECTING("CONNECTING..."), CONNECTED("CONNECTED");
+
+ private final String state;
+
+ private TerminalState(String state) {
+ this.state = state;
+ }
+
+ @Override public String toString() {
+ return state;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorDelegate.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorDelegate.java
new file mode 100644
index 0000000..8e4c853
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorDelegate.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Scharf (Wind River) - initial API and implementation
+ * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.provisional.api.provider;
+
+import static com.google.eclipse.tm.internal.terminal.provisional.api.TerminalState.CLOSED;
+
+import java.io.OutputStream;
+
+import com.google.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
+
+/**
+ * Abstract base class for all terminal connector implementations.
+ *
+ * @since org.eclipse.tm.terminal 2.0
+ */
+public abstract class TerminalConnectorDelegate {
+ // The TerminalControl associated with this connector. Required for advertising state changes when needed.
+ protected ITerminalControl terminalControl;
+
+ /**
+ * Initialize this connector. This is called once after the constructor, in order to perform any required
+ * initializations such as loading required native libraries. Any work that may lead to runtime exceptions should be
+ * done in this method rather than in the constructor.
+ *
+ * @throws Exception when the connector fails to initialize (due to missing required libraries, for instance).
+ */
+ public void initialize() throws Exception {}
+
+ public final void connect(ITerminalControl control) {
+ this.terminalControl = control;
+ connect();
+ }
+
+ protected abstract void connect();
+
+ public final void disconnect() {
+ onDisconnect();
+ terminalControl.setState(CLOSED);
+ }
+
+ protected void onDisconnect() {}
+
+ /**
+ * Returns the terminal-to-remote stream (bytes written to this stream will be sent to the remote site). For the
+ * stream in the other direction (remote to terminal see {@link ITerminalControl#getRemoteToTerminalOutputStream()}.
+ *
+ * @return the terminal-to-remote stream.
+ */
+ public abstract OutputStream getTerminalToRemoteStream();
+
+ /**
+ * @return A string that represents the settings of the connection. This representation may be shown in the status
+ * line of the terminal view.
+ */
+ public abstract String getSettingsSummary();
+
+ /**
+ * Tests if local echo is needed. The default implementation returns {@code false}.
+ *
+ * @return {@code false} by default.
+ */
+ public boolean isLocalEcho() {
+ return false;
+ }
+
+ /**
+ * Notifies the remote site that the size of the terminal has changed.
+ *
+ * @param width the new width in characters.
+ * @param height the new height in characters.
+ */
+ public void setTerminalSize(int width, int height) {}
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/AbstractTextCanvasModel.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/AbstractTextCanvasModel.java
new file mode 100644
index 0000000..5617d05
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/AbstractTextCanvasModel.java
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.swt.graphics.Point;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+public abstract class AbstractTextCanvasModel implements ITextCanvasModel {
+ private final List<ITextCanvasModelListener> listeners = new ArrayList<ITextCanvasModelListener>();
+ private final Point selectionAnchor = new Point(0, 0);
+
+ private final ITerminalTextDataSnapshot snapshot;
+
+ private int cursorLine;
+ private int cursorColumn;
+ private boolean showCursor;
+ private long cursorTime;
+ private boolean cursorIsEnabled;
+ private int lines;
+
+ private int selectionStartLine = -1;
+ private int seletionEndLine;
+ private int selectionStartCoumn;
+ private int selectionEndColumn;
+ private ITerminalTextDataSnapshot selectionSnapshot;
+ private String currentSelection = "";
+ /**
+ * do not update while update is running
+ */
+ boolean inUpdate;
+ private int columns;
+
+ public AbstractTextCanvasModel(ITerminalTextDataSnapshot snapshot) {
+ this.snapshot = snapshot;
+ lines = this.snapshot.getHeight();
+ }
+
+ @Override public void addCellCanvasModelListener(ITextCanvasModelListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override public void removeCellCanvasModelListener(ITextCanvasModelListener listener) {
+ listeners.remove(listener);
+ }
+
+ private void fireCellRangeChanged(int x, int y, int width, int height) {
+ for (ITextCanvasModelListener listener : listeners) {
+ listener.rangeChanged(x, y, width, height);
+ }
+ }
+
+ private void fireDimensionsChanged(int width, int height) {
+ for (ITextCanvasModelListener listener : listeners) {
+ listener.dimensionsChanged(width, height);
+ }
+ }
+
+ private void fireTerminalDataChanged() {
+ for (ITextCanvasModelListener listener : listeners) {
+ listener.terminalDataChanged();
+ }
+ }
+
+ @Override public ITerminalTextDataReadOnly getTerminalText() {
+ return snapshot;
+ }
+
+ protected ITerminalTextDataSnapshot getSnapshot() {
+ return snapshot;
+ }
+
+ private void updateSnapshot() {
+ if (!inUpdate && snapshot.isOutOfDate()) {
+ inUpdate = true;
+ try {
+ snapshot.updateSnapshot(false);
+ if (snapshot.hasTerminalChanged()) {
+ fireTerminalDataChanged();
+ }
+ // TODO why does hasDimensionsChanged not work?
+ // if (snapshot.hasDimensionsChanged()) fireDimensionsChanged();
+ if (lines != snapshot.getHeight() || columns != snapshot.getWidth()) {
+ fireDimensionsChanged(snapshot.getWidth(), snapshot.getHeight());
+ lines = snapshot.getHeight();
+ columns = snapshot.getWidth();
+ }
+ int y = snapshot.getFirstChangedLine();
+ // has any line changed?
+ if (y < Integer.MAX_VALUE) {
+ int height = snapshot.getLastChangedLine() - y + 1;
+ fireCellRangeChanged(0, y, snapshot.getWidth(), height);
+ }
+ } finally {
+ inUpdate = false;
+ }
+ }
+ }
+
+ /**
+ * This method must be called from the UI thread.
+ */
+ public void update() {
+ updateSnapshot();
+ updateSelection();
+ updateCursor();
+ }
+
+ @Override public int getCursorColumn() {
+ return cursorColumn;
+ }
+
+ @Override public int getCursorLine() {
+ return cursorLine;
+ }
+
+ @Override public boolean isCursorOn() {
+ return showCursor && cursorIsEnabled;
+ }
+
+ // TODO: should be called regularly to draw an update of the blinking cursor?
+ private void updateCursor() {
+ if (!cursorIsEnabled) {
+ return;
+ }
+ int cursorLine = getSnapshot().getCursorLine();
+ int cursorColumn = getSnapshot().getCursorColumn();
+ // If cursor at the end put it to the end of the last line.
+ if (cursorLine >= getSnapshot().getHeight()) {
+ cursorLine = getSnapshot().getHeight() - 1;
+ cursorColumn = getSnapshot().getWidth() - 1;
+ }
+ // Has the cursor moved?
+ if (this.cursorLine != cursorLine || this.cursorColumn != cursorColumn) {
+ // Hide the old cursor!
+ showCursor = false;
+ // Clean the previous cursor. Bug 206363: paint also the char to the left and right of the cursor
+ int col = this.cursorColumn;
+ int width = 2;
+ if (col > 0) {
+ col--;
+ width++;
+ }
+ fireCellRangeChanged(col, this.cursorLine, width, 1);
+ // The cursor is shown when it moves.
+ showCursor = true;
+ cursorTime = System.currentTimeMillis();
+ this.cursorLine = cursorLine;
+ this.cursorColumn = cursorColumn;
+ // Draw the new cursor
+ fireCellRangeChanged(this.cursorColumn, this.cursorLine, 1, 1);
+ } else {
+ long time = System.currentTimeMillis();
+ // TODO Make the cursor blink time customizable.
+ if (time - cursorTime > 500) {
+ showCursor = !showCursor;
+ cursorTime = time;
+ // On some windows machines, there is some leftover when updating the cursor.
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=206363
+ int col = this.cursorColumn;
+ int width = 2;
+ if (col > 0) {
+ col--;
+ width++;
+ }
+ fireCellRangeChanged(col, this.cursorLine, width, 1);
+ }
+ }
+ }
+
+ @Override public void setVisibleRectangle(int startLine, int startCol, int height, int width) {
+ snapshot.setInterestWindow(Math.max(0, startLine), Math.max(1, height));
+ update();
+ }
+
+ protected void showCursor(boolean show) {
+ showCursor = true;
+ }
+
+ @Override public void setCursorEnabled(boolean visible) {
+ cursorTime = System.currentTimeMillis();
+ showCursor = visible;
+ cursorIsEnabled = visible;
+ fireCellRangeChanged(cursorColumn, cursorLine, 1, 1);
+ }
+
+ @Override public boolean isCursorEnabled() {
+ return cursorIsEnabled;
+ }
+
+ @Override public Point getSelectionEnd() {
+ if (selectionStartLine < 0) {
+ return null;
+ }
+ return new Point(selectionEndColumn, seletionEndLine);
+ }
+
+ @Override public Point getSelectionStart() {
+ if (selectionStartLine < 0) {
+ return null;
+ }
+ return new Point(selectionStartCoumn, selectionStartLine);
+ }
+
+ @Override public Point getSelectionAnchor() {
+ if (selectionStartLine < 0) {
+ return null;
+ }
+ return new Point(selectionAnchor.x, selectionAnchor.y);
+ }
+
+ @Override public void setSelectionAnchor(Point anchor) {
+ selectionAnchor.x = anchor.x;
+ selectionAnchor.y = anchor.y;
+ }
+
+ @Override public void setSelection(int startLine, int endLine, int startColumn, int endColumn) {
+ doSetSelection(startLine, endLine, startColumn, endColumn);
+ currentSelection = extractSelectedText();
+ }
+
+ private void doSetSelection(int startLine, int endLine, int startColumn, int endColumn) {
+ Assert.isTrue(startLine < 0 || startLine <= endLine);
+ if (startLine >= 0) {
+ if (selectionSnapshot == null) {
+ selectionSnapshot = snapshot.getTerminalTextData().makeSnapshot();
+ selectionSnapshot.updateSnapshot(true);
+ }
+ } else if (selectionSnapshot != null) {
+ selectionSnapshot.detach();
+ selectionSnapshot = null;
+ }
+ int oldStart = selectionStartLine;
+ int oldEnd = seletionEndLine;
+ selectionStartLine = startLine;
+ seletionEndLine = endLine;
+ selectionStartCoumn = startColumn;
+ selectionEndColumn = endColumn;
+ if (selectionSnapshot != null) {
+ selectionSnapshot.setInterestWindow(0, selectionSnapshot.getHeight());
+ }
+ int changedStart;
+ int changedEnd;
+ if (oldStart < 0) {
+ changedStart = selectionStartLine;
+ changedEnd = seletionEndLine;
+ } else if (selectionStartLine < 0) {
+ changedStart = oldStart;
+ changedEnd = oldEnd;
+ } else {
+ changedStart = Math.min(oldStart, selectionStartLine);
+ changedEnd = Math.max(oldEnd, seletionEndLine);
+ }
+ if (changedStart >= 0) {
+ fireCellRangeChanged(0, changedStart, snapshot.getWidth(), changedEnd - changedStart + 1);
+ }
+ }
+
+ @Override public boolean hasLineSelection(int line) {
+ if (selectionStartLine < 0) {
+ return false;
+ }
+ return line >= selectionStartLine && line <= seletionEndLine;
+ }
+
+ @Override public String getSelectedText() {
+ return currentSelection;
+ }
+
+ /**
+ * Calculates the currently selected text
+ * @return the currently selected text
+ */
+ private String extractSelectedText() {
+ if (selectionStartLine < 0 || selectionStartCoumn < 0 || selectionSnapshot == null) {
+ return "";
+ }
+ StringBuilder buffer = new StringBuilder();
+ for (int line = selectionStartLine; line <= seletionEndLine; line++) {
+ String text;
+ char[] chars = selectionSnapshot.getChars(line);
+ if (chars != null) {
+ text = new String(chars);
+ if (line == seletionEndLine && selectionEndColumn >= 0) {
+ text = text.substring(0, Math.min(selectionEndColumn + 1, text.length()));
+ }
+ if (line == selectionStartLine) {
+ text = text.substring(Math.min(selectionStartCoumn, text.length()));
+ }
+ // get rid of the empty space at the end of the lines
+ text = text.replaceAll("\000+$","");
+ // null means space
+ text = text.replace('\000', ' ');
+ } else {
+ text = "";
+ }
+ buffer.append(text);
+ if (line < seletionEndLine) {
+ buffer.append('\n');
+ }
+ }
+ return buffer.toString();
+ }
+
+ private void updateSelection() {
+ if (selectionSnapshot != null && selectionSnapshot.isOutOfDate()) {
+ selectionSnapshot.updateSnapshot(true);
+ // Has the selection moved?
+ if (selectionSnapshot != null && selectionStartLine >= 0 && selectionSnapshot.getScrollWindowSize() > 0) {
+ int start = selectionStartLine + selectionSnapshot.getScrollWindowShift();
+ int end = seletionEndLine + selectionSnapshot.getScrollWindowShift();
+ if (start < 0) {
+ if (end >= 0) {
+ start = 0;
+ } else {
+ start = -1;
+ }
+ }
+ doSetSelection(start, end, selectionStartCoumn, selectionEndColumn);
+ }
+ // Check if the content of the selection has changed. If the content has changed, clear the selection.
+ if (currentSelection.length() > 0 && selectionSnapshot != null
+ && selectionSnapshot.getFirstChangedLine() <= seletionEndLine
+ && selectionSnapshot.getLastChangedLine() >= selectionStartLine) {
+ // Has the selected text changed?
+ if (!currentSelection.equals(extractSelectedText())) {
+ setSelection(-1, -1, -1, -1);
+ }
+ }
+ // Update the observed window...
+ if (selectionSnapshot != null) {
+ // TODO make -1 to work!
+ selectionSnapshot.setInterestWindow(0, selectionSnapshot.getHeight());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/GridCanvas.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/GridCanvas.java
new file mode 100644
index 0000000..b927d16
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/GridCanvas.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A Grid based Canvas. The canvas has rows and columns. CellPainting is done with the abstract method drawCell
+ */
+public abstract class GridCanvas extends VirtualCanvas {
+ private int cellWidth;
+ private int cellHeight;
+
+ public GridCanvas(Composite parent, int style) {
+ super(parent, style);
+ addListener(SWT.MouseWheel, new Listener() {
+ @Override public void handleEvent(Event event) {
+ if (getVerticalBar().isVisible()) {
+ int delta = -cellHeight;
+ if (event.count < 0) {
+ delta = -delta;
+ }
+ scrollYDelta(delta);
+ }
+ event.doit = false;
+ }
+ });
+ }
+
+ @Override protected void paint(GC gc) {
+ Rectangle clipping = gc.getClipping();
+ if (clipping.width == 0 || clipping.height == 0) {
+ return;
+ }
+ Rectangle clientArea = getScreenRectInVirtualSpace();
+ // Beginning coordinates.
+ int xOffset = clientArea.x;
+ int yOffset = clientArea.y;
+ int colFirst = virtualXToCell(xOffset + clipping.x);
+ if (colFirst > getCols()) {
+ colFirst = getCols();
+ } else if (colFirst < 0) {
+ colFirst = 0;
+ }
+ int rowFirst = virtualYToCell(yOffset + clipping.y);
+ // End coordinates.
+ int colLast = virtualXToCell(xOffset + clipping.x + clipping.width + cellWidth);
+ if (colLast > getCols()) {
+ colLast = getCols();
+ }
+ int rowLast = virtualYToCell(yOffset + clipping.y + clipping.height + cellHeight);
+ if (rowLast > getRows()) {
+ rowLast = getRows();
+ }
+ // Draw the cells.
+ for (int row = rowFirst; row <= rowLast; row++) {
+ int cx = colFirst * cellWidth - xOffset;
+ int cy = row * cellHeight - yOffset;
+ drawLine(gc, row, cx, cy, colFirst, colLast);
+ }
+ paintUnoccupiedSpace(gc, clipping);
+ }
+
+ abstract void drawLine(GC gc, int row, int x, int y, int colFirst, int colLast);
+
+ abstract protected int getRows();
+
+ abstract protected int getCols();
+
+ protected void setCellWidth(int cellWidth) {
+ this.cellWidth = cellWidth;
+ getHorizontalBar().setIncrement(this.cellWidth);
+ }
+
+ public int getCellWidth() {
+ return cellWidth;
+ }
+
+ protected void setCellHeight(int cellHeight) {
+ this.cellHeight = cellHeight;
+ getVerticalBar().setIncrement(this.cellHeight);
+ }
+
+ public int getCellHeight() {
+ return cellHeight;
+ }
+
+ int virtualXToCell(int x) {
+ return x / cellWidth;
+ }
+
+ int virtualYToCell(int y) {
+ return y / cellHeight;
+ }
+
+ protected Point screenPointToCell(int x, int y) {
+ x = screenXtoVirtual(x) / cellWidth;
+ y = screenYtoVirtual(y) / cellHeight;
+ return new Point(x, y);
+ }
+
+ Point screenPointToCell(Point point) {
+ return screenPointToCell(point.x, point.y);
+ }
+
+ protected Point cellToOriginOnScreen(int x, int y) {
+ x = virtualXtoScreen(cellWidth * x);
+ y = virtualYtoScreen(cellHeight * y);
+ return new Point(x, y);
+ }
+
+ Point cellToOriginOnScreen(Point cell) {
+ return cellToOriginOnScreen(cell.x, cell.y);
+ }
+
+ Rectangle getCellScreenRect(Point cell) {
+ return getCellScreenRect(cell.x, cell.y);
+ }
+
+ Rectangle getCellScreenRect(int x, int y) {
+ x = cellWidth * virtualXtoScreen(x);
+ y = cellHeight * virtualYtoScreen(y);
+ return new Rectangle(x, y, cellWidth, cellHeight);
+ }
+
+ protected Rectangle getCellVirtualRect(Point cell) {
+ return getCellVirtualRect(cell.x, cell.y);
+ }
+
+ Rectangle getCellVirtualRect(int x, int y) {
+ x = cellWidth * x;
+ y = cellHeight * y;
+ return new Rectangle(x, y, cellWidth, cellHeight);
+ }
+
+ @Override protected void viewRectangleChanged(int x, int y, int width, int height) {
+ int cellX = virtualXToCell(x);
+ int cellY = virtualYToCell(y);
+ // End coordinates
+ int xE = virtualXToCell(x + width);
+ // if(xE>getCols())
+ // xE=getCols();
+ int yE = virtualYToCell(y + height);
+ // if(yE>getRows())
+ // yE=getRows();
+ visibleCellRectangleChanged(cellX, cellY, xE - cellX, yE - cellY);
+ }
+
+ protected void visibleCellRectangleChanged(int x, int y, int width, int height) {}
+
+ @Override protected void setVirtualExtend(int width, int height) {
+ int cellHeight = getCellHeight();
+ if (cellHeight > 0) {
+ height -= height % cellHeight;
+ }
+ super.setVirtualExtend(width, height);
+ }
+
+ @Override protected void setVirtualOrigin(int x, int y) {
+ int cellHeight = getCellHeight();
+ if (cellHeight > 0) {
+ int remainder = y % cellHeight;
+ if (remainder < 0) {
+ y -= (cellHeight + remainder);
+ } else {
+ y -= remainder;
+ }
+ }
+ super.setVirtualOrigin(x, y);
+ }
+
+ @Override protected void scrollY(ScrollBar vBar) {
+ int vSelection = vBar.getSelection();
+ Rectangle bounds = getVirtualBounds();
+ int y = -vSelection;
+ int cellHeight = getCellHeight();
+ if (cellHeight > 0) {
+ int remainder = y % cellHeight;
+ if (remainder < 0) {
+ y -= (cellHeight + remainder);
+ } else {
+ y -= remainder;
+ }
+ }
+ int deltaY = y - bounds.y;
+ if (deltaY != 0) {
+ scrollSmart(0, deltaY);
+ setVirtualOrigin(bounds.x, bounds.y += deltaY);
+ }
+ if (-bounds.y + getRows() * getCellHeight() >= bounds.height) {
+ // Scrolled to bottom - need to redraw bottom area
+ Rectangle clientRect = getClientArea();
+ redraw(0, clientRect.height - this.cellHeight, clientRect.width, this.cellHeight, false);
+ }
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
new file mode 100644
index 0000000..2ae2c8a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import org.eclipse.swt.graphics.*;
+
+public interface ILinelRenderer {
+ int getCellWidth();
+
+ int getCellHeight();
+
+ void drawLine(ITextCanvasModel model, GC gc, int line, int x, int y, int firstColumn, int lastColumn);
+
+ void onFontChange();
+
+ void setInvertedColors(boolean invert);
+
+ Color getDefaultBackgroundColor();
+
+ void setColors(RGB background, RGB foreground);
+
+ void setFont(Font font);
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModel.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModel.java
new file mode 100644
index 0000000..ffd6ace
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModel.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import org.eclipse.swt.graphics.Point;
+
+import com.google.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
+
+public interface ITextCanvasModel {
+ void addCellCanvasModelListener(ITextCanvasModelListener listener);
+
+ void removeCellCanvasModelListener(ITextCanvasModelListener listener);
+
+ ITerminalTextDataReadOnly getTerminalText();
+
+ void setVisibleRectangle(int startLine, int startCol, int height, int width);
+
+ /**
+ * Indicates whether the cursor is shown (used for blinking cursors.)
+ *
+ * @return {@code true} if the cursor is shown, {@code false} otherwise.
+ */
+ boolean isCursorOn();
+
+ boolean isCursorEnabled();
+
+ /**
+ * Show/Hide the cursor.
+ *
+ * @param visible indicates whether the cursor should be visible.
+ */
+ void setCursorEnabled(boolean visible);
+
+ int getCursorLine();
+
+ int getCursorColumn();
+
+ Point getSelectionStart();
+
+ Point getSelectionEnd();
+
+ Point getSelectionAnchor();
+
+ void setSelectionAnchor(Point anchor);
+
+ // Negative 'startLine' clears the selection.
+ void setSelection(int startLine, int endLine, int startColumn, int endColumn);
+
+ boolean hasLineSelection(int line);
+
+ String getSelectedText();
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModelListener.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModelListener.java
new file mode 100644
index 0000000..55d73cc
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModelListener.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+public interface ITextCanvasModelListener {
+ void rangeChanged(int col, int line, int width, int height);
+
+ void dimensionsChanged(int cols, int rows);
+
+ /**
+ * Called when any text change happened. Used to scroll to the end of text in auto scroll mode. This does not get
+ * fired when the window of interest has changed.
+ */
+ void terminalDataChanged();
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/PipedInputStream.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/PipedInputStream.java
new file mode 100644
index 0000000..35daac0
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/PipedInputStream.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 1996, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import java.io.*;
+
+import com.google.eclipse.tm.internal.terminal.util.BoundedByteBuffer;
+
+/**
+ * Starts a {@code Runnable} in the display thread when data is available and to pretend no data is available after a
+ * given amount of time the {@code Runnable} is running.
+ */
+public class PipedInputStream extends InputStream {
+ // The output stream used by the terminal back-end to write to the terminal
+ protected final OutputStream outputStream;
+
+ // A blocking byte queue.
+ private final BoundedByteBuffer queue;
+
+ /**
+ * Constructor.
+ *
+ * @param bufferSize the size of the buffer of the output stream.
+ */
+ public PipedInputStream(int bufferSize) {
+ outputStream = new PipedOutputStream();
+ queue = new BoundedByteBuffer(bufferSize);
+ }
+
+ /**
+ * Returns the output stream used by the back-end to write to the terminal.
+ *
+ * @return the output stream used by the back-end to write to the terminal.
+ */
+ public OutputStream getOutputStream() {
+ return outputStream;
+ }
+
+ /**
+ * Waits until data is available for reading.
+ *
+ * @param time the time wait, in milliseconds.
+ * @throws InterruptedException when the thread is interrupted while waiting for the buffer to become ready.
+ */
+ public void waitForAvailable(long time) throws InterruptedException {
+ synchronized (queue) {
+ if (queue.size() == 0 && !queue.isClosed()) {
+ queue.wait(time);
+ }
+ }
+ }
+
+ @Override public int available() {
+ synchronized (queue) {
+ return queue.size();
+ }
+ }
+
+ @Override public int read() throws IOException {
+ try {
+ synchronized (queue) {
+ return queue.read();
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return -1;
+ }
+ }
+
+ @Override public void close() throws IOException {
+ synchronized (queue) {
+ queue.close();
+ }
+ }
+
+ @Override public int read(byte[] b, int off, int len) throws IOException {
+ if (len == 0) {
+ return 0;
+ }
+ int n = 0;
+ // Read as much as we can using a single synchronized statement.
+ try {
+ synchronized (queue) {
+ // If nothing available, block and read one byte.
+ if (queue.size() == 0) {
+ // Block now until at least one byte is available.
+ int c = queue.read();
+ // Are we at the end of stream?
+ if (c == -1) {
+ return -1;
+ }
+ b[off] = (byte) c;
+ n++;
+ }
+ // Is there more data available?
+ if (n < len && queue.size() > 0) {
+ // Read at most available.
+ int available = Math.min(queue.size(), len - n);
+ // Are we at the end of the stream?
+ if (available == 0 && queue.isClosed()) {
+ // If no byte was read, return -1 to indicate end of stream; otherwise return the bytes we read up to now.
+ if (n == 0) {
+ n = -1;
+ }
+ return n;
+ }
+ queue.read(b, off + n, available);
+ n += available;
+ }
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ return n;
+ }
+
+ /**
+ * An output stream that calls {@link PipedInputStream#textAvailable} every time data is written to the stream. The
+ * data is written to {@link PipedInputStream#queue}.
+ */
+ private class PipedOutputStream extends OutputStream {
+ @Override public void write(byte[] b, int off, int len) throws IOException {
+ try {
+ synchronized (queue) {
+ if (queue.isClosed()) {
+ throw new IOException("Stream is closed!");
+ }
+ int written = 0;
+ while (written < len) {
+ if (queue.getFreeSlots() == 0) {
+ // If no slots available, write one byte and block until free slots are available.
+ queue.write(b[off + written]);
+ written++;
+ } else {
+ // If slots are available, write as much as we can in one junk
+ int n = Math.min(queue.getFreeSlots(), len - written);
+ queue.write(b, off + written, n);
+ written += n;
+ }
+ }
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Override public void write(int b) throws IOException {
+ try {
+ synchronized (queue) {
+ if (queue.isClosed()) {
+ throw new IOException("Stream is closed!");
+ }
+ queue.write((byte) b);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Override public void close() throws IOException {
+ synchronized (queue) {
+ queue.close();
+ }
+ }
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/PollingTextCanvasModel.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/PollingTextCanvasModel.java
new file mode 100644
index 0000000..803254c
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/PollingTextCanvasModel.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import org.eclipse.swt.widgets.Display;
+
+import com.google.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
+
+public class PollingTextCanvasModel extends AbstractTextCanvasModel {
+ private int pollInterval = 50;
+
+ public PollingTextCanvasModel(ITerminalTextDataSnapshot snapshot) {
+ super(snapshot);
+ Display.getDefault().timerExec(pollInterval, new Runnable() {
+ @Override public void run() {
+ update();
+ Display.getDefault().timerExec(pollInterval, this);
+ }
+ });
+ }
+
+ public void setUpdateInterval(int interval) {
+ pollInterval = interval;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/StyleMap.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/StyleMap.java
new file mode 100644
index 0000000..92a4a9f
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/StyleMap.java
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import java.util.*;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.Display;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+public class StyleMap {
+ private static final String BLACK = "black";
+ private static final String WHITE = "white";
+ private static final String WHITE_FOREGROUND = "white_foreground";
+ private static final String GRAY = "gray";
+ private static final String MAGENTA = "magenta";
+ private static final String CYAN = "cyan";
+ private static final String YELLOW = "yellow";
+ private static final String BLUE = "blue";
+ private static final String GREEN = "green";
+ private static final String RED = "red";
+
+ private static final String PREFIX = "org.eclipse.tm.internal.";
+
+ // TODO propagate the name of the font in the FontRegistry
+ private static final String DEFAULT_FONT_NAME = "terminal.views.view.font.definition";
+
+ private String fontName = DEFAULT_FONT_NAME;
+
+ private final Map<StyleColor, Color> colorMapForeground = new HashMap<StyleColor, Color>();
+ private final Map<StyleColor, Color> colorMapBackground = new HashMap<StyleColor, Color>();
+ private final Map<StyleColor, Color> colorMapIntense = new HashMap<StyleColor, Color>();
+
+ private Point charSize;
+
+ private final Style defaultStyle;
+
+ private boolean invertColors;
+ private boolean proportional;
+
+ private final int[] offsets = new int[256];
+
+ private RGB background = new RGB(0, 0, 0);
+ private RGB foreground = new RGB(229, 229, 229);
+
+ private Font font = JFaceResources.getFontRegistry().get(fontName);
+
+ StyleMap() {
+ initColors();
+ defaultStyle = Style.getStyle(StyleColor.getStyleColor(BLACK), StyleColor.getStyleColor(WHITE));
+ updateFont();
+ }
+
+ private void initColors() {
+ initForegroundColors();
+ initBackgroundColors();
+ initIntenseColors();
+ }
+
+ private void initForegroundColors() {
+ if (invertColors) {
+ setColor(colorMapForeground, WHITE, 0, 0, 0);
+ setColor(colorMapForeground, WHITE_FOREGROUND, 50, 50, 50);
+ setColor(colorMapForeground, BLACK, foreground.red, foreground.green, foreground.blue); // set foreground
+ } else {
+ setColor(colorMapForeground, WHITE, 255, 255, 255);
+ setColor(colorMapForeground, WHITE_FOREGROUND, 229, 229, 229);
+ setColor(colorMapForeground, BLACK, 50, 50, 50);
+ }
+ setColor(colorMapForeground, RED, 205, 0, 0);
+ setColor(colorMapForeground, GREEN, 0, 205, 0);
+ setColor(colorMapForeground, BLUE, 0, 0, 238);
+ setColor(colorMapForeground, YELLOW, 205, 205, 0);
+ setColor(colorMapForeground, CYAN, 0, 205, 205);
+ setColor(colorMapForeground, MAGENTA, 205, 0, 205);
+ setColor(colorMapForeground, GRAY, 229, 229, 229);
+ }
+
+ private void initBackgroundColors() {
+ if (invertColors) {
+ setColor(colorMapBackground, WHITE, background.red, background.green, background.blue); // set background
+ setColor(colorMapBackground, WHITE_FOREGROUND, 50, 50, 50); // only used when colors are inverse
+ setColor(colorMapBackground, BLACK, foreground.red, foreground.green, foreground.blue); // set cursor color
+ } else {
+ setColor(colorMapBackground, WHITE, 255, 255, 255);
+ setColor(colorMapBackground, WHITE_FOREGROUND, 229, 229, 229);
+ setColor(colorMapBackground, BLACK, 0, 0, 0);
+ }
+ setColor(colorMapBackground, RED, 205, 0, 0);
+ setColor(colorMapBackground, GREEN, 0, 205, 0);
+ setColor(colorMapBackground, BLUE, 0, 0, 238);
+ setColor(colorMapBackground, YELLOW, 205, 205, 0);
+ setColor(colorMapBackground, CYAN, 0, 205, 205);
+ setColor(colorMapBackground, MAGENTA, 205, 0, 205);
+ setColor(colorMapBackground, GRAY, 229, 229, 229);
+ }
+
+ private void initIntenseColors() {
+ if (invertColors) {
+ setColor(colorMapIntense, WHITE, 127, 127, 127);
+ setColor(colorMapIntense, WHITE_FOREGROUND, 0, 0, 0); // only used when colors are inverse
+ setColor(colorMapIntense, BLACK, 255, 255, 255);
+ } else {
+ setColor(colorMapIntense, WHITE, 255, 255, 255);
+ setColor(colorMapIntense, WHITE_FOREGROUND, 255, 255, 255);
+ setColor(colorMapIntense, BLACK, 0, 0, 0);
+ }
+ setColor(colorMapIntense, RED, 255, 0, 0);
+ setColor(colorMapIntense, GREEN, 0, 255, 0);
+ setColor(colorMapIntense, BLUE, 92, 92, 255);
+ setColor(colorMapIntense, YELLOW, 255, 255, 0);
+ setColor(colorMapIntense, CYAN, 0, 255, 255);
+ setColor(colorMapIntense, MAGENTA, 255, 0, 255);
+ setColor(colorMapIntense, GRAY, 255, 255, 255);
+ }
+
+ private void setColor(Map<StyleColor, Color> colorMap, String name, int r, int g, int b) {
+ String colorName = PREFIX + r + "-" + g + "-" + b;
+ Color color = JFaceResources.getColorRegistry().get(colorName);
+ if (color == null) {
+ JFaceResources.getColorRegistry().put(colorName, new RGB(r, g, b));
+ color = JFaceResources.getColorRegistry().get(colorName);
+ }
+ colorMap.put(StyleColor.getStyleColor(name), color);
+ colorMap.put(StyleColor.getStyleColor(name.toUpperCase()), color);
+ }
+
+ public Color getForegrondColor(Style style) {
+ style = defaultIfNull(style);
+ Map<StyleColor, Color> map = style.isBold() ? colorMapIntense : colorMapForeground;
+ if (style.isReverse()) {
+ return getColor(map, style.getBackground());
+ }
+ return getColor(map, style.getForground());
+ }
+
+ public Color getBackgroundColor(Style style) {
+ style = defaultIfNull(style);
+ if (style.isReverse()) {
+ return getColor(colorMapBackground, style.getForground());
+ }
+ return getColor(colorMapBackground, style.getBackground());
+ }
+
+ Color getColor(Map<StyleColor, Color> map, StyleColor color) {
+ Color c = map.get(color);
+ if (c == null) {
+ c = Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
+ }
+ return c;
+ }
+
+ private Style defaultIfNull(Style style) {
+ if (style == null) {
+ style = defaultStyle;
+ }
+ return style;
+ }
+
+ public void setInvertedColors(boolean invert) {
+ if (invert == invertColors) {
+ return;
+ }
+ invertColors = invert;
+ initColors();
+ }
+
+ public Font getFont(Style style) {
+ style = defaultIfNull(style);
+ FontData fontDatas[] = font.getFontData();
+ FontData data = fontDatas[0];
+ if (style.isBold()) {
+ return new Font(font.getDevice(), data.getName(), data.getHeight(), data.getStyle() | SWT.BOLD);
+ }
+ if (style.isUnderline()) {
+ return new Font(font.getDevice(), data.getName(), data.getHeight(), data.getStyle() | SWT.ITALIC);
+ }
+ return font;
+ }
+
+ public Font getFont() {
+ return font;
+ }
+
+ public int getFontWidth() {
+ return charSize.x;
+ }
+
+ public int getFontHeight() {
+ return charSize.y;
+ }
+
+ public void updateFont() {
+ Display display = Display.getCurrent();
+ GC gc = new GC(display);
+ if (JFaceResources.getFontRegistry().hasValueFor(DEFAULT_FONT_NAME)) {
+ fontName = DEFAULT_FONT_NAME;
+ } else if (JFaceResources.getFontRegistry().hasValueFor("REMOTE_COMMANDS_VIEW_FONT")) {
+ // try RSE Shell View Font
+ fontName = "REMOTE_COMMANDS_VIEW_FONT";
+ } else {
+ // fall back to "basic jface text font"
+ fontName = "org.eclipse.jface.textfont";
+ }
+ gc.setFont(getFont());
+ charSize = gc.textExtent("W");
+ proportional = false;
+ for (char c = ' '; c <= '~'; c++) {
+ // Consider only the first 128 chars for deciding if a font is proportional.
+ if (measureChar(gc, c, true)) {
+ proportional = true;
+ }
+ }
+ // TODO should we also consider the upper 128 chars?
+ for (char c = ' ' + 128; c <= '~' + 128; c++) {
+ measureChar(gc, c, false);
+ }
+ if (proportional) {
+ charSize.x -= 2; // Works better on small fonts.
+ }
+ for (int i = 0; i < offsets.length; i++) {
+ offsets[i] = (charSize.x - offsets[i]) / 2;
+ }
+ if (!proportional) {
+ // Measure font in boldface, too, and if wider then treat like proportional.
+ gc.setFont(getFont(defaultStyle.setBold(true)));
+ Point charSizeBold = gc.textExtent("W");
+ if (charSize.x != charSizeBold.x) {
+ proportional = true;
+ }
+ }
+ gc.dispose();
+ }
+
+ private boolean measureChar(GC gc, char c, boolean updateMax) {
+ boolean proportional = false;
+ Point extent = gc.textExtent(String.valueOf(c));
+ if (extent.x > 0 && extent.y > 0 && (charSize.x != extent.x || charSize.y != extent.y)) {
+ proportional = true;
+ if (updateMax) {
+ charSize.x = Math.max(charSize.x, extent.x);
+ charSize.y = Math.max(charSize.y, extent.y);
+ }
+ }
+ offsets[c] = extent.x;
+ return proportional;
+ }
+
+ public boolean isFontProportional() {
+ return proportional;
+ }
+
+ /**
+ * Return the offset in pixels required to center a given character.
+ *
+ * @param c the character to measure.
+ * @return the offset in x direction to center this character.
+ */
+ public int getCharOffset(char c) {
+ if (c >= offsets.length) {
+ return 0;
+ }
+ return offsets[c];
+ }
+
+ public void setColors(RGB background, RGB foreground) {
+ this.background = background;
+ this.foreground = foreground;
+ initColors();
+ }
+
+ public void setFont(Font font) {
+ this.font = font;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
new file mode 100644
index 0000000..a7f46b3
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
@@ -0,0 +1,395 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A cell oriented Canvas. Maintains a list of "cells". It can either be vertically or horizontally scrolled. The
+ * CellRenderer is responsible for painting the cell.
+ */
+public class TextCanvas extends GridCanvas {
+ protected final ITextCanvasModel cellCanvasModel;
+ private final ILinelRenderer cellRenderer;
+ private boolean scrollLockOn;
+ private Point draggingStart;
+ private Point draggingEnd;
+ private boolean hasSelection;
+ private ResizeListener resizeListener;
+
+ // The minSize is meant to determine the minimum size of the backing store (grid) into which remote data is rendered.
+ // If the viewport is smaller than that minimum size, the backing store size remains at the minSize,and a scrollbar is
+ // shown instead. In reality, this has the following issues or effects today:
+ //
+ // (a) Bug 281328: For very early data coming in before the widget is realized, the minSize determines into what
+ // initial grid that is rendered. See also {@link #addResizeHandler(ResizeListener)}.
+ //
+ // (b) Bug 294468: Since we have redraw and size computation problems with horizontal scrollers, for now the
+ // minColumns must be small enough to avoid a horizontal scroller appearing in most cases.
+ //
+ // (c) Bug 294327: Since we have problems with the vertical scroller showing the correct location, minLines must be
+ // small enough to avoid a vertical scroller or new data may be rendered off-screen.
+ //
+ // As a compromise, we have been working with a 20x4 since the terminal inception, though many users would want a
+ // 80x24 minSize and backing store.
+
+ // Pros and cons of the small minsize:
+ // + consistent "remote size==viewport size", vi works as expected
+ // - dumb terminals which expect 80x24 render garbled on small viewport
+ //
+ // If bug 294468 were resolved, an 80 wide minSize would be preferrable since it allows switching the terminal
+ // viewport small/large as needed, without destroying the backing store. For a complete solution, bug 196462 tracks
+ // the request for a user-defined fixed-widow-size-mode.
+ private int minColumns = 80;
+
+ private int minLines = 4;
+ private boolean cursorEnabled;
+ private boolean resizing;
+
+ /**
+ * Create a new CellCanvas with the given SWT style bits. (SWT.H_SCROLL and SWT.V_SCROLL are automatically added).
+ */
+ public TextCanvas(Composite parent, ITextCanvasModel model, int style, ILinelRenderer cellRenderer) {
+ super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
+ this.cellRenderer = cellRenderer;
+ setCellWidth(cellRenderer.getCellWidth());
+ setCellHeight(cellRenderer.getCellHeight());
+ cellCanvasModel = model;
+ cellCanvasModel.addCellCanvasModelListener(new ITextCanvasModelListener() {
+ @Override public void rangeChanged(int col, int line, int width, int height) {
+ repaintRange(col, line, width, height);
+ }
+
+ @Override public void dimensionsChanged(int cols, int rows) {
+ calculateGrid();
+ }
+
+ @Override public void terminalDataChanged() {
+ if (!isDisposed() && !resizing) {
+ // scroll to end (unless scroll lock is active)
+ calculateGrid();
+ scrollToEnd();
+ }
+ }
+ });
+ // let the cursor blink if the text canvas gets the focus...
+ addFocusListener(new FocusListener() {
+ @Override public void focusGained(FocusEvent e) {
+ cellCanvasModel.setCursorEnabled(cursorEnabled);
+ }
+
+ @Override public void focusLost(FocusEvent e) {
+ cellCanvasModel.setCursorEnabled(false);
+ }
+ });
+ addMouseListener(new MouseAdapter() {
+ @Override public void mouseDown(MouseEvent e) {
+ if (e.button == 1) { // left button
+ draggingStart = screenPointToCell(e.x, e.y);
+ hasSelection = false;
+ if ((e.stateMask & SWT.SHIFT) != 0) {
+ Point anchor = cellCanvasModel.getSelectionAnchor();
+ if (anchor != null) {
+ draggingStart = anchor;
+ }
+ } else {
+ cellCanvasModel.setSelectionAnchor(draggingStart);
+ }
+ draggingEnd = null;
+ }
+ }
+
+ @Override public void mouseUp(MouseEvent e) {
+ if (e.button == 1) { // left button
+ updateHasSelection(e);
+ if (hasSelection) {
+ setSelection(screenPointToCell(e.x, e.y));
+ } else {
+ cellCanvasModel.setSelection(-1, -1, -1, -1);
+ }
+ draggingStart = null;
+ }
+ }
+ });
+ addMouseMoveListener(new MouseMoveListener() {
+ @Override public void mouseMove(MouseEvent e) {
+ if (draggingStart != null) {
+ updateHasSelection(e);
+ setSelection(screenPointToCell(e.x, e.y));
+ }
+ }
+ });
+ serVerticalBarVisible(true);
+ setHorizontalBarVisible(false);
+ }
+
+ // The user has to drag the mouse to at least one character to make a selection. Once this is done, even a one char
+ // selection is OK.
+ private void updateHasSelection(MouseEvent e) {
+ if (draggingStart != null) {
+ Point p = screenPointToCell(e.x, e.y);
+ if (draggingStart.x != p.x || draggingStart.y != p.y) {
+ hasSelection = true;
+ }
+ }
+ }
+
+ void setSelection(Point p) {
+ if (draggingStart != null && !p.equals(draggingEnd)) {
+ draggingEnd = p;
+ if (compare(p, draggingStart) < 0) {
+ // bug 219589 - make sure selection start coordinates are non-negative
+ int startColumn = Math.max(0, p.x);
+ int startRow = Math.max(p.y, 0);
+ cellCanvasModel.setSelection(startRow, draggingStart.y, startColumn, draggingStart.x);
+ } else {
+ cellCanvasModel.setSelection(draggingStart.y, p.y, draggingStart.x, p.x);
+ }
+ }
+ }
+
+ int compare(Point p1, Point p2) {
+ if (p1.equals(p2)) {
+ return 0;
+ }
+ if (p1.y == p2.y) {
+ return p1.x > p2.x ? 1 : -1;
+ }
+ return p1.y > p2.y ? 1 : -1;
+ }
+
+ public ILinelRenderer getCellRenderer() {
+ return cellRenderer;
+ }
+
+ public int getMinColumns() {
+ return minColumns;
+ }
+
+ public void setMinColumns(int minColumns) {
+ this.minColumns = minColumns;
+ }
+
+ public int getMinLines() {
+ return minLines;
+ }
+
+ public void setMinLines(int minLines) {
+ this.minLines = minLines;
+ }
+
+ protected void onResize(boolean init) {
+ if (resizeListener != null) {
+ Rectangle bonds = getClientArea();
+ int cellHeight = getCellHeight();
+ int cellWidth = getCellWidth();
+ int lines = bonds.height / cellHeight;
+ int columns = bonds.width / cellWidth;
+ // When the view is minimized, its size is set to 0 we don't sent this to the terminal!
+ if ((lines > 0 && columns > 0) || init) {
+ if (columns < minColumns) {
+ if (!isHorizontalBarVisble()) {
+ setHorizontalBarVisible(true);
+ bonds = getClientArea();
+ lines = bonds.height / cellHeight;
+ }
+ columns = minColumns;
+ } else if (columns >= minColumns && isHorizontalBarVisble()) {
+ setHorizontalBarVisible(false);
+ bonds = getClientArea();
+ lines = bonds.height / cellHeight;
+ columns = bonds.width / cellWidth;
+ }
+ if (lines < minLines) {
+ lines = minLines;
+ }
+ resizeListener.sizeChanged(lines, columns);
+ }
+ }
+ super.onResize();
+ calculateGrid();
+ }
+
+ @Override protected void onResize() {
+ resizing = true;
+ try {
+ onResize(false);
+ } finally {
+ resizing = false;
+ }
+ }
+
+ private void calculateGrid() {
+ Rectangle virtualBounds = getVirtualBounds();
+ setRedraw(false);
+ try {
+ setVirtualExtend(getCols() * getCellWidth(), getRows() * getCellHeight());
+ getParent().layout();
+ if (resizing) {
+ // scroll to end if view port was near last line
+ Rectangle viewRect = getViewRectangle();
+ if (virtualBounds.height - (viewRect.y + viewRect.height) < getCellHeight() * 2) {
+ scrollToEnd();
+ }
+ }
+ } finally {
+ setRedraw(true);
+ }
+ }
+
+ void scrollToEnd() {
+ if (!scrollLockOn) {
+ int y = -(getRows() * getCellHeight() - getClientArea().height);
+ if (y > 0) {
+ y = 0;
+ }
+ Rectangle v = getViewRectangle();
+ if (v.y != -y) {
+ setVirtualOrigin(v.x, y);
+ }
+ // make sure the scroll area is correct.
+ scrollY(getVerticalBar());
+ scrollX(getHorizontalBar());
+ }
+ }
+
+ public boolean isScrollLockOn() {
+ return scrollLockOn;
+ }
+
+ public void setScrollLockOn(boolean on) {
+ scrollLockOn = on;
+ }
+
+ protected void repaintRange(int col, int line, int width, int height) {
+ Point origin = cellToOriginOnScreen(col, line);
+ Rectangle r = new Rectangle(origin.x, origin.y, width * getCellWidth(), height * getCellHeight());
+ repaint(r);
+ }
+
+ @Override protected void drawLine(GC gc, int line, int x, int y, int colFirst, int colLast) {
+ cellRenderer.drawLine(cellCanvasModel, gc, line, x, y, colFirst, colLast);
+ }
+
+ @Override protected Color getTerminalBackgroundColor() {
+ return cellRenderer.getDefaultBackgroundColor();
+ }
+
+ @Override protected void visibleCellRectangleChanged(int x, int y, int width, int height) {
+ cellCanvasModel.setVisibleRectangle(y, x, height, width);
+ update();
+ }
+
+ @Override protected int getCols() {
+ return cellCanvasModel.getTerminalText().getWidth();
+ }
+
+ @Override protected int getRows() {
+ return cellCanvasModel.getTerminalText().getHeight();
+ }
+
+ public String getSelectionText() {
+ // TODO -- create a hasSelectionMethod!
+ return cellCanvasModel.getSelectedText();
+ }
+
+ public void copy() {
+ Clipboard clipboard = new Clipboard(getDisplay());
+ clipboard.setContents(new Object[] { getSelectionText() }, new Transfer[] { TextTransfer.getInstance() });
+ clipboard.dispose();
+ }
+
+ public void selectAll() {
+ cellCanvasModel.setSelection(
+ 0, cellCanvasModel.getTerminalText().getHeight(), 0, cellCanvasModel.getTerminalText().getWidth());
+ cellCanvasModel.setSelectionAnchor(new Point(0, 0));
+ }
+
+ public boolean isEmpty() {
+ return false;
+ }
+
+ /**
+ * Gets notified when the visible size of the terminal changes. This should update the model!
+ */
+ public static interface ResizeListener {
+ void sizeChanged(int lines, int columns);
+ }
+
+ public void addResizeHandler(ResizeListener listener) {
+ if (resizeListener != null) {
+ throw new IllegalArgumentException("There can be at most one listener at the moment!");
+ }
+ resizeListener = listener;
+ // Bug 281328: The very first few characters might be missing in the terminal control if opened and connected
+ // programmatically.
+ //
+ // In case the terminal had not been visible yet or is too small (less than one line visible), the terminal should
+ // have a minimum size to avoid RuntimeExceptions.
+ Rectangle bonds = getClientArea();
+ if (bonds.height < getCellHeight() || bonds.width < getCellWidth()) {
+ // Widget not realized yet, or minimized to < 1 item. Just tell the listener our min size.
+ resizeListener.sizeChanged(getMinLines(), getMinColumns());
+ } else {
+ // Widget realized: compute actual size and force telling the listener
+ onResize(true);
+ }
+ }
+
+ public void onFontChange() {
+ cellRenderer.onFontChange();
+ setCellWidth(cellRenderer.getCellWidth());
+ setCellHeight(cellRenderer.getCellHeight());
+ calculateGrid();
+ }
+
+ public void setInvertedColors(boolean invert) {
+ cellRenderer.setInvertedColors(invert);
+ redraw();
+ }
+
+ /**
+ * Indicates whether the cursor is enabled (blinking.) By default the cursor is not enabled.
+ *
+ * @return {@code true} if the cursor is enabled, {@code false} otherwise.
+ */
+ public boolean isCursorEnabled() {
+ return cursorEnabled;
+ }
+
+ /**
+ * Enables or disables the cursor (enabling means that the cursor blinks.)
+ *
+ * @param enabled indicates whether the cursor should be enabled.
+ */
+ public void setCursorEnabled(boolean enabled) {
+ if (enabled != cursorEnabled) {
+ cursorEnabled = enabled;
+ cellCanvasModel.setCursorEnabled(cursorEnabled);
+ }
+ }
+
+ public void setColors(RGB background, RGB foreground) {
+ cellRenderer.setColors(background, foreground);
+ redraw();
+ }
+
+ @Override public void setFont(Font font) {
+ super.setFont(font);
+ cellRenderer.setFont(font);
+ redraw();
+ }
+
+ @Override public Point screenPointToCell(int x, int y) {
+ return super.screenPointToCell(x, y);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
new file mode 100644
index 0000000..f3c2ed3
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import static org.eclipse.swt.SWT.*;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.Display;
+
+import com.google.eclipse.tm.terminal.model.*;
+
+public class TextLineRenderer implements ILinelRenderer {
+ private final ITextCanvasModel model;
+ private final StyleMap styleMap = new StyleMap();
+
+ public TextLineRenderer(TextCanvas c, ITextCanvasModel model) {
+ this.model = model;
+ }
+
+ @Override public int getCellWidth() {
+ return styleMap.getFontWidth();
+ }
+
+ @Override public int getCellHeight() {
+ return styleMap.getFontHeight();
+ }
+
+ @Override public void drawLine(
+ ITextCanvasModel model, GC gc, int line, int x, int y, int firstColumn, int lastColumn) {
+ if (line < 0 || line >= getTerminalText().getHeight() || firstColumn >= getTerminalText().getWidth()
+ || firstColumn - lastColumn == 0) {
+ fillBackground(gc, x, y, getCellWidth() * (lastColumn - firstColumn), getCellHeight());
+ return;
+ }
+ lastColumn = Math.min(lastColumn, getTerminalText().getWidth());
+ LineSegment[] segments = getTerminalText().getLineSegments(line, firstColumn, lastColumn - firstColumn);
+ for (int i = 0; i < segments.length; i++) {
+ LineSegment segment = segments[i];
+ Style style = segment.getStyle();
+ setupGC(gc, style);
+ String text = segment.getText();
+ drawText(gc, x, y, firstColumn, segment.getColumn(), text);
+ drawCursor(model, gc, line, x, y, firstColumn);
+ }
+ if (this.model.hasLineSelection(line)) {
+ Display display = Display.getCurrent();
+ gc.setForeground(display.getSystemColor(COLOR_LIST_SELECTION_TEXT));
+ gc.setBackground(display.getSystemColor(COLOR_LIST_SELECTION));
+ Point start = model.getSelectionStart();
+ Point end = model.getSelectionEnd();
+ char[] chars = model.getTerminalText().getChars(line);
+ if (chars == null) {
+ return;
+ }
+ int offset = 0;
+ if (start.y == line) {
+ offset = start.x;
+ }
+ offset = Math.max(offset, firstColumn);
+ int len;
+ if (end.y == line) {
+ len = end.x - offset + 1;
+ } else {
+ len = chars.length - offset + 1;
+ }
+ len = Math.min(len, chars.length - offset);
+ if (len > 0) {
+ String text = new String(chars, offset, len);
+ drawText(gc, x, y, firstColumn, offset, text);
+ }
+ }
+ }
+
+ private void fillBackground(GC gc, int x, int y, int width, int height) {
+ Color bg = gc.getBackground();
+ gc.setBackground(getDefaultBackgroundColor());
+ gc.fillRectangle(x, y, width, height);
+ gc.setBackground(bg);
+ }
+
+ @Override public Color getDefaultBackgroundColor() {
+ // null == default style
+ return styleMap.getBackgroundColor(null);
+ }
+
+ private void drawCursor(ITextCanvasModel model, GC gc, int row, int x, int y, int colFirst) {
+ if (!model.isCursorOn()) {
+ return;
+ }
+ int cursorLine = model.getCursorLine();
+ if (row == cursorLine) {
+ int cursorColumn = model.getCursorColumn();
+ if (cursorColumn < getTerminalText().getWidth()) {
+ Style style = getTerminalText().getStyle(row, cursorColumn);
+ if (style == null) {
+ // TODO make the cursor color customizable
+ style = Style.getStyle("BLACK", "WHITE");
+ }
+ style = style.setReverse(!style.isReverse());
+ setupGC(gc, style);
+ String text = String.valueOf(getTerminalText().getChar(row, cursorColumn));
+ drawText(gc, x, y, colFirst, cursorColumn, text);
+ }
+ }
+ }
+
+ private void drawText(GC gc, int x, int y, int colFirst, int col, String text) {
+ int offset = (col - colFirst) * getCellWidth();
+ if (styleMap.isFontProportional()) {
+ // Draw the background.
+ // TODO why does this not work?
+ // gc.fillRectangle(x, y, styleMap.getFontWidth() * text.length(), styleMap.getFontHeight());
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ int newX = x + offset + i * styleMap.getFontWidth();
+ // TODO why do I have to draw the background character by character?
+ gc.fillRectangle(newX, y, styleMap.getFontWidth(), styleMap.getFontHeight());
+ if (c != ' ' && c != '\000') {
+ gc.drawString(String.valueOf(c), styleMap.getCharOffset(c) + newX, y, true);
+ }
+ }
+ } else {
+ text = text.replace('\000', ' ');
+ gc.drawString(text, x + offset, y, false);
+ }
+ }
+
+ private void setupGC(GC gc, Style style) {
+ Color c = styleMap.getForegrondColor(style);
+ if (c != gc.getForeground()) {
+ gc.setForeground(c);
+ }
+ c = styleMap.getBackgroundColor(style);
+ if (c != gc.getBackground()) {
+ gc.setBackground(c);
+ }
+ Font f = styleMap.getFont(style);
+ if (f != gc.getFont()) {
+ gc.setFont(f);
+ }
+ }
+
+ ITerminalTextDataReadOnly getTerminalText() {
+ return model.getTerminalText();
+ }
+
+ @Override public void onFontChange() {
+ styleMap.updateFont();
+ }
+
+ @Override public void setInvertedColors(boolean invert) {
+ styleMap.setInvertedColors(invert);
+
+ }
+
+ @Override public void setColors(RGB background, RGB foreground) {
+ styleMap.setColors(background, foreground);
+ }
+
+ @Override public void setFont(Font font) {
+ styleMap.setFont(font);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/VirtualCanvas.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/VirtualCanvas.java
new file mode 100644
index 0000000..2d66ad3
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/textcanvas/VirtualCanvas.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.internal.terminal.textcanvas;
+
+import static org.eclipse.core.runtime.IStatus.*;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+import com.google.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
+
+/**
+ * A {@code Canvas} showing a virtual object. Virtual: the extent of the total canvas. Screen: the visible client area
+ * in the screen.
+ */
+public abstract class VirtualCanvas extends Canvas {
+ private final Rectangle virtualBounds = new Rectangle(0, 0, 0, 0);
+
+ /** Called when the viewed part is changing. */
+ private final Rectangle viewRectangle = new Rectangle(0, 0, 0, 0);
+
+ private Rectangle clientArea;
+
+ /** Prevent infinite loop in {@link #updateScrollbars()} */
+ private boolean inUpdateScrollbars;
+
+ private static boolean inUpdateScrollbarsLogged;
+
+ public VirtualCanvas(Composite parent, int style) {
+ super(parent, style | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE);
+ clientArea = getClientArea();
+ addListener(SWT.Paint, new Listener() {
+ @Override public void handleEvent(Event event) {
+ paint(event.gc);
+ }
+ });
+ addListener(SWT.Resize, new Listener() {
+ @Override public void handleEvent(Event event) {
+ clientArea = getClientArea();
+ onResize();
+ }
+ });
+ getVerticalBar().addListener(SWT.Selection, new Listener() {
+ @Override public void handleEvent(Event e) {
+ scrollY((ScrollBar) e.widget);
+ }
+ });
+ getHorizontalBar().addListener(SWT.Selection, new Listener() {
+ @Override public void handleEvent(Event e) {
+ scrollX((ScrollBar) e.widget);
+ }
+ });
+ }
+
+ protected void onResize() {
+ updateViewRectangle();
+ }
+
+ protected void scrollX(ScrollBar horizontalBar) {
+ int selection = horizontalBar.getSelection();
+ int destinationX = -selection - virtualBounds.x;
+ virtualBounds.x = -selection;
+ scrollSmart(destinationX, 0);
+ updateViewRectangle();
+ }
+
+ protected void scrollXDelta(int delta) {
+ getHorizontalBar().setSelection(-virtualBounds.x + delta);
+ scrollX(getHorizontalBar());
+ }
+
+ protected void scrollY(ScrollBar vBar) {
+ int vSelection = vBar.getSelection();
+ int destY = -vSelection - virtualBounds.y;
+ if (destY != 0) {
+ virtualBounds.y = -vSelection;
+ scrollSmart(0, destY);
+ updateViewRectangle();
+ }
+ }
+
+ protected void scrollYDelta(int delta) {
+ getVerticalBar().setSelection(-virtualBounds.y + delta);
+ scrollY(getVerticalBar());
+ }
+
+ protected void scrollSmart(int deltaX, int deltaY) {
+ if (deltaX != 0 || deltaY != 0) {
+ Rectangle rect = getBounds();
+ scroll(deltaX, deltaY, 0, 0, rect.width, rect.height, false);
+ }
+ }
+
+ protected void revealRect(Rectangle rect) {
+ Rectangle visibleRect = getScreenRectInVirtualSpace();
+ // scroll the X part
+ int deltaX = 0;
+ if (rect.x < visibleRect.x) {
+ deltaX = rect.x - visibleRect.x;
+ } else if (visibleRect.x + visibleRect.width < rect.x + rect.width) {
+ deltaX = (rect.x + rect.width) - (visibleRect.x + visibleRect.width);
+ }
+ if (deltaX != 0) {
+ getHorizontalBar().setSelection(-virtualBounds.x + deltaX);
+ scrollX(getHorizontalBar());
+ }
+ // scroll the Y part
+ int deltaY = 0;
+ if (rect.y < visibleRect.y) {
+ deltaY = rect.y - visibleRect.y;
+ } else if (visibleRect.y + visibleRect.height < rect.y + rect.height) {
+ deltaY = (rect.y + rect.height) - (visibleRect.y + visibleRect.height);
+ }
+ if (deltaY != 0) {
+ getVerticalBar().setSelection(-virtualBounds.y + deltaY);
+ scrollY(getVerticalBar());
+ }
+ }
+
+ protected void repaint(Rectangle r) {
+ if (isDisposed()) {
+ return;
+ }
+ if (inClipping(r, clientArea)) {
+ redraw(r.x, r.y, r.width, r.height, true);
+ update();
+ }
+ }
+
+ abstract protected void paint(GC gc);
+
+ protected Color getTerminalBackgroundColor() {
+ return getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+ }
+
+ protected void paintUnoccupiedSpace(GC gc, Rectangle clipping) {
+ int width = virtualBounds.width + virtualBounds.x;
+ int height = virtualBounds.height + virtualBounds.y;
+ int marginWidth = (clipping.x + clipping.width) - width;
+ int marginHeight = (clipping.y + clipping.height) - height;
+ if (marginWidth > 0 || marginHeight > 0) {
+ Color background = getBackground();
+ gc.setBackground(getTerminalBackgroundColor());
+ if (marginWidth > 0) {
+ gc.fillRectangle(width, clipping.y, marginWidth, clipping.height);
+ }
+ if (marginHeight > 0) {
+ gc.fillRectangle(clipping.x, height, clipping.width, marginHeight);
+ }
+ gc.setBackground(background);
+ }
+ }
+
+ protected boolean inClipping(Rectangle clipping, Rectangle r) {
+ // TODO check if this is OK in all cases (the <=!)
+ if (r.x + r.width <= clipping.x) {
+ return false;
+ }
+ if (clipping.x + clipping.width <= r.x) {
+ return false;
+ }
+ if (r.y + r.height <= clipping.y) {
+ return false;
+ }
+ if (clipping.y + clipping.height <= r.y) {
+ return false;
+ }
+ return true;
+ }
+
+ protected Rectangle getScreenRectInVirtualSpace() {
+ return new Rectangle(
+ clientArea.x - virtualBounds.x, clientArea.y - virtualBounds.y, clientArea.width, clientArea.height);
+ }
+
+ protected Rectangle getRectInVirtualSpace(Rectangle r) {
+ return new Rectangle(r.x - virtualBounds.x, r.y - virtualBounds.y, r.width, r.height);
+ }
+
+ protected void setVirtualExtend(int width, int height) {
+ virtualBounds.width = width;
+ virtualBounds.height = height;
+ updateScrollbars();
+ updateViewRectangle();
+ }
+
+ protected void setVirtualOrigin(int x, int y) {
+ if (virtualBounds.x != x || virtualBounds.y != y) {
+ virtualBounds.x = x;
+ virtualBounds.y = y;
+ getHorizontalBar().setSelection(-x);
+ getVerticalBar().setSelection(-y);
+ updateViewRectangle();
+ }
+ }
+
+ protected Rectangle getVirtualBounds() {
+ return cloneRectangle(virtualBounds);
+ }
+
+ protected int virtualXtoScreen(int x) {
+ return x + virtualBounds.x;
+ }
+
+ protected int virtualYtoScreen(int y) {
+ return y + virtualBounds.y;
+ }
+
+ protected int screenXtoVirtual(int x) {
+ return x - virtualBounds.x;
+ }
+
+ protected int screenYtoVirtual(int y) {
+ return y - virtualBounds.y;
+ }
+
+ protected void updateViewRectangle() {
+ if (viewRectangle.x == -virtualBounds.x && viewRectangle.y == -virtualBounds.y
+ && viewRectangle.width == clientArea.width && viewRectangle.height == clientArea.height) {
+ return;
+ }
+ viewRectangle.x = -virtualBounds.x;
+ viewRectangle.y = -virtualBounds.y;
+ viewRectangle.width = clientArea.width;
+ viewRectangle.height = clientArea.height;
+ viewRectangleChanged(viewRectangle.x, viewRectangle.y, viewRectangle.width, viewRectangle.height);
+ }
+
+ protected Rectangle getViewRectangle() {
+ return cloneRectangle(viewRectangle);
+ }
+
+ private Rectangle cloneRectangle(Rectangle r) {
+ return new Rectangle(r.x, r.y, r.width, r.height);
+ }
+
+ protected void viewRectangleChanged(int x, int y, int width, int height) {}
+
+ private void updateScrollbars() {
+ // don't get into infinite loops....
+ if (!inUpdateScrollbars) {
+ inUpdateScrollbars = true;
+ try {
+ doUpdateScrollbar();
+ } finally {
+ inUpdateScrollbars = false;
+ }
+ } else {
+ if (!inUpdateScrollbarsLogged) {
+ inUpdateScrollbarsLogged = true;
+ ILog logger = TerminalPlugin.getDefault().getLog();
+ logger.log(new Status(WARNING, TerminalPlugin.PLUGIN_ID, OK, "Unexpected Recursion in terminal", null));
+ }
+ }
+ }
+
+ private void doUpdateScrollbar() {
+ Rectangle clientArea = getClientArea();
+ ScrollBar horizontal = getHorizontalBar();
+ // Even if setVisible was called on the scrollbar, isVisible returns false if its parent is not visible.
+ if (!isVisible() || horizontal.isVisible()) {
+ horizontal.setPageIncrement(clientArea.width - horizontal.getIncrement());
+ int max = virtualBounds.width;
+ horizontal.setMaximum(max);
+ horizontal.setThumb(clientArea.width);
+ }
+ ScrollBar vertical = getVerticalBar();
+ // even if setVisible was called on the scrollbar, isVisible returns false if its parent is not visible.
+ if (!isVisible() || vertical.isVisible()) {
+ vertical.setPageIncrement(clientArea.height - vertical.getIncrement());
+ int max = virtualBounds.height;
+ vertical.setMaximum(max);
+ vertical.setThumb(clientArea.height);
+ }
+ }
+
+ protected boolean isVertialBarVisible() {
+ return getVerticalBar().isVisible();
+ }
+
+ protected void serVerticalBarVisible(boolean showVScrollBar) {
+ ScrollBar vertical = getVerticalBar();
+ vertical.setVisible(showVScrollBar);
+ vertical.setSelection(0);
+ }
+
+ protected boolean isHorizontalBarVisble() {
+ return getHorizontalBar().isVisible();
+ }
+
+ protected void setHorizontalBarVisible(boolean showHScrollBar) {
+ ScrollBar horizontal = getHorizontalBar();
+ horizontal.setVisible(showHScrollBar);
+ horizontal.setSelection(0);
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/util/BoundedByteBuffer.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/util/BoundedByteBuffer.java
new file mode 100644
index 0000000..d0e5bac
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/internal/terminal/util/BoundedByteBuffer.java
@@ -0,0 +1,138 @@
+package com.google.eclipse.tm.internal.terminal.util;
+
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * A byte bounded buffer used to synchronize the input and the output stream.
+ * <p>
+ * Adapted from {@code BoundedBufferWithStateTracking} http://gee.cs.oswego.edu/dl/cpj/allcode.java
+ * http://gee.cs.oswego.edu/dl/cpj/
+ * <p>
+ * BoundedBufferWithStateTracking is part of the examples for the book Concurrent Programming in Java: Design
+ * Principles and Patterns by Doug Lea (ISBN 0-201-31009-0). Second edition published by Addison-Wesley, November
+ * 1999. The code is Copyright(c) Douglas Lea 1996, 1999 and released to the public domain and may be used for any
+ * purposes whatsoever.
+ * <p>
+ * For some reasons a solution based on PipedOutputStream/PipedIntputStream does work *very* slowly:
+ * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4404700
+ * <p>
+ */
+public class BoundedByteBuffer {
+ private final byte[] buffer; // the elements
+ private int putPosition; // circular indices
+ private int takePosition;
+ private int usedSlots; // the count
+ private boolean closed;
+
+ public BoundedByteBuffer(int capacity) throws IllegalArgumentException {
+ // Make sure we don't deadlock on too small capacity.
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("Capacity should be greater than zero");
+ }
+ buffer = new byte[capacity];
+ }
+
+ /**
+ * Returns the bytes available for {@link #read()}.
+ *
+ * @return the bytes available for reading.
+ */
+ public int size() {
+ return usedSlots;
+ }
+
+ /**
+ * Writes a single byte to the buffer. Blocks if the buffer is full.
+ *
+ * @param b byte to write to the buffer.
+ * @throws InterruptedException when the thread is interrupted while waiting for the buffer to become ready.
+ */
+ public void write(byte b) throws InterruptedException {
+ while (usedSlots == buffer.length) {
+ // Wait until not full.
+ wait();
+ }
+ buffer[putPosition] = b;
+ putPosition = (putPosition + 1) % buffer.length; // cyclically increment
+ if (usedSlots++ == 0) {
+ notifyAll();
+ }
+ }
+
+ public int getFreeSlots() {
+ return buffer.length - usedSlots;
+ }
+
+ public void write(byte[] b, int off, int len) throws InterruptedException {
+ assert len <= getFreeSlots();
+ while (usedSlots == buffer.length) {
+ // Wait until not full.
+ wait();
+ }
+ int n = Math.min(len, buffer.length - putPosition);
+ System.arraycopy(b, off, buffer, putPosition, n);
+ if (putPosition + len > buffer.length) {
+ System.arraycopy(b, off + n, buffer, 0, len - n);
+ }
+ putPosition = (putPosition + len) % buffer.length; // cyclically increment
+ boolean wasEmpty = usedSlots == 0;
+ usedSlots += len;
+ if (wasEmpty) {
+ notifyAll();
+ }
+ }
+
+ /**
+ * Read a single byte. Blocks until a byte is available.
+ *
+ * @return a byte from the buffer.
+ * @throws InterruptedException when the thread is interrupted while waiting for the buffer to become ready.
+ */
+ public byte read() throws InterruptedException {
+ while (usedSlots == 0) {
+ if (closed) {
+ return -1;
+ }
+ // Wait until not empty.
+ wait();
+ }
+ byte b = buffer[takePosition];
+ takePosition = (takePosition + 1) % buffer.length;
+ if (usedSlots-- == buffer.length) {
+ notifyAll();
+ }
+ return b;
+ }
+
+ public int read(byte[] b, int off, int len) throws InterruptedException {
+ Assert.isTrue(len <= size());
+ while (usedSlots == 0) {
+ if (closed) {
+ return 0;
+ }
+ // Wait until not empty.
+ wait();
+ }
+ int n = Math.min(len, buffer.length - takePosition);
+ System.arraycopy(buffer, takePosition, b, off, n);
+ if (takePosition + len > n) {
+ System.arraycopy(buffer, 0, b, off + n, len - n);
+ }
+ takePosition = (takePosition + len) % buffer.length;
+ boolean wasFull = usedSlots == buffer.length;
+ usedSlots -= len;
+ if (wasFull) {
+ notifyAll();
+ }
+ return len;
+ }
+
+ public void close() {
+ closed = true;
+ notifyAll();
+ }
+
+ public boolean isClosed() {
+ return closed;
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextData.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextData.java
new file mode 100644
index 0000000..a37d2d6
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextData.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+/**
+ * A writable matrix of characters and {@link Style}. This is intended to be the low level representation of the text of
+ * a Terminal. Higher layers are responsible to fill the text and styles into this representation.
+ */
+public interface ITerminalTextData extends ITerminalTextDataReadOnly {
+
+ void setDimensions(int height, int width);
+
+ void setMaxHeight(int height);
+
+ int getMaxHeight();
+
+ void setChar(int line, int column, char c, Style style);
+
+ void setChars(int line, int column, char[] chars, Style style);
+
+ void setChars(int line, int column, char[] chars, int start, int len, Style style);
+
+ void cleanLine(int line);
+
+ /**
+ * Shifts some lines up or down. The "empty" space is filled with {@code '\000'} chars and {@code null} {@link Style}.
+ * <p>
+ * To illustrate shift, here is some sample data:
+ * <pre>
+ * 0 aaaa
+ * 1 bbbb
+ * 2 cccc
+ * 3 dddd
+ * 4 eeee
+ * </pre>
+ *
+ * Shift a region of 3 lines <b>up</b> by one line {@code shift(1,3,-1)}
+ * <pre>
+ * 0 aaaa
+ * 1 cccc
+ * 2 dddd
+ * 3
+ * 4 eeee
+ * </pre>
+ *
+ * Shift a region of 3 lines <b>down</b> by one line {@code shift(1,3,1)}
+ * <pre>
+ * 0 aaaa
+ * 1
+ * 2 bbbb
+ * 3 cccc
+ * 4 eeee
+ * </pre>
+ *
+ * @param startLine the start line of the shift.
+ * @param size the number of lines to shift.
+ * @param shift how much scrolling is done. New scrolled area is filled with {@code '\000'}. A negative number means
+ * scroll down, positive scroll up (see example above).
+ */
+ void scroll(int startLine, int size, int shift);
+
+ /**
+ * Adds a new line to the terminal. If maxHeigth is reached, the entire terminal will be scrolled. Else a line will be
+ * added.
+ */
+ void addLine();
+
+ void copy(ITerminalTextData source);
+
+ void copyLine(ITerminalTextData source, int sourceLine, int destinationLine);
+
+ void copyRange(ITerminalTextData source, int sourceStartLine, int destinationStartLine, int length);
+
+ void setCursorLine(int line);
+
+ void setCursorColumn(int column);
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextDataReadOnly.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextDataReadOnly.java
new file mode 100644
index 0000000..cca29d0
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextDataReadOnly.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+public interface ITerminalTextDataReadOnly {
+ int getWidth();
+
+ int getHeight();
+
+ LineSegment[] getLineSegments(int line, int startCol, int numberOfCols);
+
+ char getChar(int line, int column);
+
+ Style getStyle(int line, int column);
+
+ /**
+ * Creates a new instance of {@link ITerminalTextDataSnapshot} that can be used to track changes. Make sure to call
+ * {@link ITerminalTextDataSnapshot#detach()} if you don't need the snapshots anymore.
+ * <p>
+ * <b>Note: </b>A new snapshot is empty and needs a call to {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)}
+ * to get its initial values. You might want to setup the snapshot to your needs by calling
+ * {@link ITerminalTextDataSnapshot#setInterestWindow(int, int)}.
+ * </p>
+ *
+ * @return a new instance of {@link ITerminalTextDataSnapshot} that "listens" to changes of this one.
+ */
+ public ITerminalTextDataSnapshot makeSnapshot();
+
+ char[] getChars(int line);
+
+ Style[] getStyles(int line);
+
+ int getCursorLine();
+
+ int getCursorColumn();
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextDataSnapshot.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextDataSnapshot.java
new file mode 100644
index 0000000..19b0f4a
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/ITerminalTextDataSnapshot.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Scharf (Wind River) - initial API and implementation
+ * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+/**
+ * Maintains a snapshot of an instance of {@link ITerminalTextData}. While the {@link ITerminalTextData} continues
+ * changing, the snapshot remains unchanged until the next snapshot is taken by calling
+ * {@link #updateSnapshot(boolean)}. This is important, because the {@link ITerminalTextData} might get modified by
+ * another thread.
+ */
+public interface ITerminalTextDataSnapshot extends ITerminalTextDataReadOnly {
+ /**
+ * This listener gets called when the current snapshot is out of date. Calling
+ * {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)} will have an effect. Once the
+ * {@link #snapshotOutOfDate(ITerminalTextDataSnapshot)} method is called, it will not be called until
+ * {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)} is called and a new snapshot needs to be updated again.
+ */
+ interface SnapshotOutOfDateListener {
+ /**
+ * Gets called when the snapshot is out of date. To get the snapshot up to date, call
+ * {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)}.
+ *
+ * @param snapshot The snapshot that is out of date.
+ */
+ void snapshotOutOfDate(ITerminalTextDataSnapshot snapshot);
+ }
+
+ void addListener(SnapshotOutOfDateListener listener);
+
+ void removeListener(SnapshotOutOfDateListener listener);
+
+ /**
+ * Ends the listening to the {@link ITerminalTextData}. After this has been called no new snapshot data is collected.
+ */
+ void detach();
+
+ boolean isOutOfDate();
+
+ /**
+ * The window of interest is the region the snapshot should track. Changes outside this region are ignored. The change
+ * takes effect after an update.
+ * @param startLine -1 means track the end of the data.
+ * @param size number of lines to track. A size of -1 means track all.
+ */
+ void setInterestWindow(int startLine, int size);
+
+ int getInterestWindowStartLine();
+
+ int getInterestWindowSize();
+
+ /**
+ * Create a new snapshot of the {@link ITerminalTextData}. It will efficiently copy the data of the
+ * {@link ITerminalTextData} into an internal representation. The snapshot also keeps track of the changes since the
+ * previous snapshot.
+ * <p>
+ * With the methods {@link #getFirstChangedLine()}, {@link #getLastChangedLine()} and {@link #hasLineChanged(int)} you
+ * can find out what has changed in the current snapshot since the previous snapshot.
+ * </p>
+ * <p>
+ * If {@code detectScrolling} is {@code true} the information about scrolling can be retrieved using the following methods:
+ * {@link #getScrollWindowStartLine()}, {@link #getScrollWindowSize()} and {@link #getScrollWindowShift()}.
+ * </p>
+ * <p>
+ * <b>Note:</b> The method {@link #hasLineChanged(int)} returns changes <b>after</b> the scrolling has been applied.
+ * </p>
+ *
+ * @param detectScrolling indicates whether the snapshot should try to identify scroll changes since the last
+ * snapshot.
+ */
+ void updateSnapshot(boolean detectScrolling);
+
+ /**
+ * Returns the first line changed in this snapshot compared to the previous snapshot.
+ * <p>
+ * <b>Note:</b> If no line has changed, this returns {@link Integer#MAX_VALUE}.
+ * <p>
+ * <b>Note:</b> if {@link #updateSnapshot(boolean)} has been called with <code>true</code>, then this does not include
+ * lines that only have been scrolled. This is the first line that has changed <b>after</b> the scroll has been
+ * applied.
+ *
+ * @return the first line changed in this snapshot compared to the previous snapshot.
+ */
+ int getFirstChangedLine();
+
+ /**
+ * Returns the last line changed in this snapshot compared to the previous snapshot. If the height has changed since
+ * the last update of the snapshot, then the returned value is within the new dimensions.
+ * <p>
+ * <b>Note:</b> If no line has changed, this returns <code>-1</code>
+ * <p>
+ * <b>Note:</b> if {@link #updateSnapshot(boolean)} has been called with <code>true</code>, then this does not include
+ * lines that only have been scrolled. This is the last line that has changed <b>after</b> the scroll has been
+ * applied.
+ * <p>
+ * A typical for loop using this method would look like this (note the <code><=</code> in the for loop):
+ * <pre>
+ * for (int line = snap.{@link #getFirstChangedLine()}; line <b><=</b> snap.getLastChangedLine(); line++)
+ * if(snap.{@link #hasLineChanged(int) hasLineChanged(line)})
+ * doSomething(line);
+ * </pre>
+ * @return the last line changed in this snapshot compared to the previous snapshot.
+ */
+ int getLastChangedLine();
+
+ boolean hasLineChanged(int line);
+
+ boolean hasDimensionsChanged();
+
+ boolean hasTerminalChanged();
+
+ /**
+ * If {@link #updateSnapshot(boolean)} was called with {@code true}, then this method returns the top of the scroll
+ * region.
+ *
+ * @return The first line scrolled in this snapshot compared to the previous snapshot.
+ *
+ * @see ITerminalTextData#scroll(int, int, int)
+ */
+ int getScrollWindowStartLine();
+
+ /**
+ * If {@link #updateSnapshot(boolean)} was called with {@code true}, then this method returns the size of the scroll
+ * region. If nothing has changed, 0 is returned.
+ *
+ * @return The number of lines scrolled in this snapshot compared to the previous snapshot.
+ *
+ * @see ITerminalTextData#scroll(int, int, int)
+ */
+ int getScrollWindowSize();
+
+ /**
+ * If {@link #updateSnapshot(boolean)} was called with {@code true}, then this method returns number of lines moved by
+ * the scroll region.
+ *
+ * @return The the scroll shift of this snapshot compared to the previous snapshot.
+ *
+ * @see ITerminalTextData#scroll(int, int, int)
+ */
+ int getScrollWindowShift();
+
+ ITerminalTextData getTerminalTextData();
+}
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/LineSegment.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/LineSegment.java
new file mode 100644
index 0000000..3e07093
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/LineSegment.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Scharf (Wind River) - initial API and implementation
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+public class LineSegment {
+ private final int column;
+ private final String text;
+ private final Style style;
+
+ public LineSegment(int column, String text, Style style) {
+ this.column = column;
+ this.text = text;
+ this.style = style;
+ }
+
+ public int getColumn() {
+ return column;
+ }
+
+ public Style getStyle() {
+ return style;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ @Override public String toString() {
+ return "LineSegment(" + column + ", \"" + text + "\"," + style + ")";
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/Style.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/Style.java
new file mode 100644
index 0000000..d8f9a58
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/Style.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+import java.util.*;
+
+// TODO add an Object for user data, use weak map to keep track of styles with associated user data.
+public class Style {
+ private final StyleColor forground;
+ private final StyleColor background;
+ private final boolean bold;
+ private final boolean blink;
+ private final boolean underline;
+ private final boolean reverse;
+
+ private static final Map<Style, Style> STYLES = new HashMap<Style, Style>();
+
+ private Style(StyleColor forground, StyleColor background, boolean bold, boolean blink, boolean underline,
+ boolean reverse) {
+ this.forground = forground;
+ this.background = background;
+ this.bold = bold;
+ this.blink = blink;
+ this.underline = underline;
+ this.reverse = reverse;
+ }
+
+ public static Style getStyle(StyleColor forground, StyleColor background, boolean bold, boolean blink,
+ boolean underline, boolean reverse) {
+ Style style = new Style(forground, background, bold, blink, underline, reverse);
+ Style cached;
+ synchronized (STYLES) {
+ cached = STYLES.get(style);
+ if (cached == null) {
+ cached = style;
+ STYLES.put(cached, cached);
+ }
+ }
+ return cached;
+ }
+
+ public static Style getStyle(String forground, String background) {
+ return getStyle(
+ StyleColor.getStyleColor(forground), StyleColor.getStyleColor(background), false, false, false, false);
+ }
+
+ public static Style getStyle(StyleColor forground, StyleColor background) {
+ return getStyle(forground, background, false, false, false, false);
+ }
+
+ public Style setForground(StyleColor forground) {
+ return getStyle(forground, background, bold, blink, underline, reverse);
+ }
+
+ public Style setBackground(StyleColor background) {
+ return getStyle(forground, background, bold, blink, underline, reverse);
+ }
+
+ public Style setForground(String colorName) {
+ return getStyle(StyleColor.getStyleColor(colorName), background, bold, blink, underline, reverse);
+ }
+
+ public Style setBackground(String colorName) {
+ return getStyle(forground, StyleColor.getStyleColor(colorName), bold, blink, underline, reverse);
+ }
+
+ public Style setBold(boolean bold) {
+ return getStyle(forground, background, bold, blink, underline, reverse);
+ }
+
+ public Style setBlink(boolean blink) {
+ return getStyle(forground, background, bold, blink, underline, reverse);
+ }
+
+ public Style setUnderline(boolean underline) {
+ return getStyle(forground, background, bold, blink, underline, reverse);
+ }
+
+ public Style setReverse(boolean reverse) {
+ return getStyle(forground, background, bold, blink, underline, reverse);
+ }
+
+ public StyleColor getBackground() {
+ return background;
+ }
+
+ public boolean isBlink() {
+ return blink;
+ }
+
+ public boolean isBold() {
+ return bold;
+ }
+
+ public StyleColor getForground() {
+ return forground;
+ }
+
+ public boolean isReverse() {
+ return reverse;
+ }
+
+ public boolean isUnderline() {
+ return underline;
+ }
+
+ @Override public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((background == null) ? 0 : background.hashCode());
+ result = prime * result + (blink ? 1231 : 1237);
+ result = prime * result + (bold ? 1231 : 1237);
+ result = prime * result + ((forground == null) ? 0 : forground.hashCode());
+ result = prime * result + (reverse ? 1231 : 1237);
+ result = prime * result + (underline ? 1231 : 1237);
+ return result;
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Style other = (Style) obj;
+ if (background != other.background) {
+ return false;
+ }
+ if (blink != other.blink) {
+ return false;
+ }
+ if (bold != other.bold) {
+ return false;
+ }
+ if (forground != other.forground) {
+ return false;
+ }
+ if (reverse != other.reverse) {
+ return false;
+ }
+ return underline == other.underline;
+ }
+
+ @Override public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Style [forground=");
+ builder.append(forground);
+ builder.append(", background=");
+ builder.append(background);
+ builder.append(", bold=");
+ builder.append(bold);
+ builder.append(", blink=");
+ builder.append(blink);
+ builder.append(", underline=");
+ builder.append(underline);
+ builder.append(", reverse=");
+ builder.append(reverse);
+ builder.append("]");
+ return builder.toString();
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/StyleColor.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/StyleColor.java
new file mode 100644
index 0000000..7846207
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/StyleColor.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+import java.util.*;
+
+public class StyleColor {
+ private static final Map<String, StyleColor> STYLE_COLORS = new HashMap<String, StyleColor>();
+
+ private final String name;
+
+ public static StyleColor getStyleColor(String name) {
+ StyleColor result;
+ synchronized (STYLE_COLORS) {
+ result = STYLE_COLORS.get(name);
+ if (result == null) {
+ result = new StyleColor(name);
+ STYLE_COLORS.put(name, result);
+ }
+ }
+ return result;
+ }
+
+ private StyleColor(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override public String toString() {
+ return name;
+ }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/TerminalTextDataFactory.java b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/TerminalTextDataFactory.java
new file mode 100644
index 0000000..a9c014b
--- /dev/null
+++ b/com.google.eclipse.tm.terminal/src/com/google/eclipse/tm/terminal/model/TerminalTextDataFactory.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package com.google.eclipse.tm.terminal.model;
+
+import com.google.eclipse.tm.internal.terminal.model.*;
+
+public class TerminalTextDataFactory {
+ public static ITerminalTextData makeTerminalTextData() {
+ return new SynchronizedTerminalTextData(new TerminalTextData());
+ }
+}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/connector/TerminalConnector.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/connector/TerminalConnector.java
deleted file mode 100644
index 86ebca2..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/connector/TerminalConnector.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Michael Scharf (Wind River) - [200541] Extract from TerminalConnectorExtension.TerminalConnectorProxy
- * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl
- * Uwe Stieber (Wind River) - [282996] [terminal][api] Add "hidden" attribute to terminal connector extension point
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.connector;
-
-import java.io.OutputStream;
-
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.tm.internal.terminal.control.impl.TerminalMessages;
-import org.eclipse.tm.internal.terminal.provisional.api.ISettingsPage;
-import org.eclipse.tm.internal.terminal.provisional.api.ISettingsStore;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
-import org.eclipse.tm.internal.terminal.provisional.api.Logger;
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalConnectorExtension;
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
-
-/**
- * An {@link ITerminalConnector} instance, also known as terminal connection
- * type, for maintaining a single terminal connection.
- *
- * It provides all terminal connector functions that can be provided by static
- * markup without loading the actual implementation class. The actual
- * {@link TerminalConnectorImpl} implementation class is lazily loaded by the
- * provided {@link TerminalConnector.Factory} interface when needed. class, and
- * delegates to the actual implementation when needed. The following methods can
- * be called without initializing the contributed implementation class:
- * {@link #getId()}, {@link #getName()}, {@link #getSettingsSummary()},{@link #load(ISettingsStore)},
- * {@link #setTerminalSize(int, int)}, {@link #save(ISettingsStore)},
- * {@link #getAdapter(Class)}
- *
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- * Clients can get terminal connector instances through the
- * {@link TerminalConnectorExtension} class.
- * @since org.eclipse.tm.terminal 2.0
- */
-public class TerminalConnector implements ITerminalConnector {
- /**
- * Creates an instance of TerminalConnectorImpl. This is used to lazily load
- * classed defined in extensions.
- *
- * @since org.eclipse.tm.terminal 2.0
- */
- public interface Factory {
- /**
- * Factory method to create the actual terminal connector implementation
- * when needed.
- *
- * @return a Connector
- * @throws Exception
- */
- TerminalConnectorImpl makeConnector() throws Exception;
- }
- /**
- * The factory for creating impl instances.
- */
- private final TerminalConnector.Factory fTerminalConnectorFactory;
- /**
- * The (display) name of the TerminalConnector
- */
- private final String fName;
- /**
- * The unique id the connector
- */
- private final String fId;
- /**
- * Flag to mark the connector as hidden.
- */
- private final boolean fHidden;
- /**
- * The connector
- */
- private TerminalConnectorImpl fConnector;
- /**
- * If the initialization of the class specified in the extension fails,
- * this variable contains the error
- */
- private Exception fException;
- /**
- * The store might be set before the real connector is initialized.
- * This keeps the value until the connector is created.
- */
- private ISettingsStore fStore;
- /**
- * Constructor for the terminal connector.
- *
- * @param terminalConnectorFactory Factory for lazily instantiating the
- * TerminalConnectorImpl when needed.
- * @param id terminal connector ID. The connector is publicly known under
- * this ID.
- * @param name translatable name to display the connector in the UI.
- */
- public TerminalConnector(TerminalConnector.Factory terminalConnectorFactory, String id, String name, boolean hidden) {
- fTerminalConnectorFactory = terminalConnectorFactory;
- fId = id;
- fName = name;
- fHidden = hidden;
- }
- public String getInitializationErrorMessage() {
- getConnectorImpl();
- if(fException!=null)
- return fException.getLocalizedMessage();
- return null;
- }
- public String getId() {
- return fId;
- }
- public String getName() {
- return fName;
- }
- public boolean isHidden() {
- return fHidden;
- }
- private TerminalConnectorImpl getConnectorImpl() {
- if(!isInitialized()) {
- try {
- fConnector=fTerminalConnectorFactory.makeConnector();
- fConnector.initialize();
- } catch (Exception e) {
- fException=e;
- fConnector=new TerminalConnectorImpl(){
- public void connect(ITerminalControl control) {
- // super.connect(control);
- control.setState(TerminalState.CLOSED);
- control.setMsg(getInitializationErrorMessage());
- }
- public OutputStream getTerminalToRemoteStream() {
- return null;
- }
- public String getSettingsSummary() {
- return null;
- }};
- // that's the place where we log the exception
- Logger.logException(e);
- }
- if(fConnector!=null && fStore!=null)
- fConnector.load(fStore);
- }
- return fConnector;
- }
-
- public boolean isInitialized() {
- return fConnector!=null || fException!=null;
- }
- public void connect(ITerminalControl control) {
- getConnectorImpl().connect(control);
- }
- public void disconnect() {
- getConnectorImpl().disconnect();
- }
- public OutputStream getTerminalToRemoteStream() {
- return getConnectorImpl().getTerminalToRemoteStream();
- }
- public String getSettingsSummary() {
- if(fConnector!=null)
- return getConnectorImpl().getSettingsSummary();
- else
- return TerminalMessages.NotInitialized;
- }
- public boolean isLocalEcho() {
- return getConnectorImpl().isLocalEcho();
- }
- public void load(ISettingsStore store) {
- if(fConnector==null) {
- fStore=store;
- } else {
- getConnectorImpl().load(store);
- }
- }
- public ISettingsPage makeSettingsPage() {
- return getConnectorImpl().makeSettingsPage();
- }
- public void save(ISettingsStore store) {
- // no need to save the settings: it cannot have changed
- // because we are not initialized....
- if(fConnector!=null)
- getConnectorImpl().save(store);
- }
- public void setTerminalSize(int newWidth, int newHeight) {
- // we assume that setTerminalSize is called also after
- // the terminal has been initialized. Else we would have to cache
- // the values....
- if(fConnector!=null) {
- fConnector.setTerminalSize(newWidth, newHeight);
- }
- }
- public Object getAdapter(Class adapter) {
- TerminalConnectorImpl connector=null;
- if(isInitialized())
- connector=getConnectorImpl();
- // if we cannot create the connector then we cannot adapt...
- if(connector!=null) {
- // maybe the connector is adaptable
- if(connector instanceof IAdaptable) {
- Object result =((IAdaptable)connector).getAdapter(adapter);
- // Not sure if the next block is needed....
- if(result==null)
- //defer to the platform
- result= Platform.getAdapterManager().getAdapter(connector, adapter);
- if(result!=null)
- return result;
- }
- // maybe the real adapter is what we need....
- if(adapter.isInstance(connector))
- return connector;
- }
- // maybe we have to be adapted....
- return Platform.getAdapterManager().getAdapter(this, adapter);
- }
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/connector/TerminalToRemoteInjectionOutputStream.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/connector/TerminalToRemoteInjectionOutputStream.java
deleted file mode 100644
index bcca318..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/connector/TerminalToRemoteInjectionOutputStream.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.connector;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-class TerminalToRemoteInjectionOutputStream extends FilterOutputStream {
- /**
- * This class handles bytes written to the {@link TerminalToRemoteInjectionOutputStream}.
- */
- static abstract public class Interceptor {
- protected OutputStream fOriginal;
- /**
- * @param original the injection into the original stream begins
- * @throws IOException
- */
- public void begin(OutputStream original) throws IOException {
- fOriginal=original;
- }
- /**
- * @param b a byte was written to the {@link TerminalToRemoteInjectionOutputStream}.
- * @throws IOException
- */
- public void write(int b) throws IOException {
- }
- /**
- * @param b bytes written to the {@link TerminalToRemoteInjectionOutputStream}.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @throws IOException
- */
- public void write(byte[] b, int off, int len) throws IOException {
- }
- /**
- * The injection into the normal stream ends.
- * @throws IOException
- */
- public void close() throws IOException {
- }
- public void flush() {
- }
- }
- static public class BufferInterceptor extends Interceptor {
- private final ByteArrayOutputStream fBuffer=new ByteArrayOutputStream();
- public void close() throws IOException {
- fOriginal.write(fBuffer.toByteArray());
- }
- public void write(byte[] b, int off, int len) throws IOException {
- fBuffer.write(b, off, len);
- }
- public void write(int b) throws IOException {
- fBuffer.write(b);
- }
- }
- private class TerminalFilterOutputStream extends OutputStream {
- final private Object fLock=TerminalToRemoteInjectionOutputStream.this;
- public void close() throws IOException {
- synchronized(fLock) {
- if(fInjection==this) {
- flush();
- ungrabOutput();
- }
- }
- }
- public void write(byte[] b, int off, int len) throws IOException {
- synchronized(fLock) {
- checkStream();
- out.write(b, off, len);
- }
- }
- public void write(byte[] b) throws IOException {
- synchronized(fLock) {
- checkStream();
- out.write(b);
- }
- }
- public void flush() throws IOException {
- synchronized(fLock) {
- checkStream();
- out.flush();
- }
- }
- public void write(int b) throws IOException {
- synchronized(fLock) {
- checkStream();
- out.write(b);
- }
- }
- private void checkStream() throws IOException {
- if(fInjection!=this)
- throw new IOException("Stream is closed"); //$NON-NLS-1$
- }
- }
- private Interceptor fInterceptor;
- private TerminalFilterOutputStream fInjection;
- public TerminalToRemoteInjectionOutputStream(OutputStream out) {
- super(out);
- }
- synchronized protected void ungrabOutput() throws IOException {
- if(fInterceptor!=null) {
- fInterceptor.close();
- fInterceptor=null;
- fInjection=null;
- }
- }
- /**
- * There can only be one injection stream active at a time. You must call close on the
- * returned output stream to end the injection.
- * @param interceptor This is used handle bytes sent while the injection stream is active.
- * @return a output stream that can be used to write to the decorated stream.
- * @throws IOException
- */
- public synchronized OutputStream grabOutput(Interceptor interceptor) throws IOException {
- if(fInjection!=null) {
- throw new IOException("Buffer in use"); //$NON-NLS-1$
- }
- fInterceptor=interceptor;
- fInterceptor.begin(out);
- fInjection=new TerminalFilterOutputStream();
- return fInjection;
- }
- /** See {@link #grabOutput(TerminalToRemoteInjectionOutputStream.Interceptor)}.
- * @return injection output stream
- * @throws IOException
- */
- public synchronized OutputStream grabOutput() throws IOException {
- return grabOutput(new BufferInterceptor());
- }
- synchronized public void close() throws IOException {
- if(fInjection!=null) {
- fInjection.close();
- }
- super.close();
- }
- synchronized public void flush() throws IOException {
- if(fInterceptor!=null)
- fInterceptor.flush();
- out.flush();
- }
- synchronized public void write(byte[] b, int off, int len) throws IOException {
- if(fInterceptor!=null)
- fInterceptor.write(b, off, len);
- else
- out.write(b, off, len);
- }
- synchronized public void write(int b) throws IOException {
- if(fInterceptor!=null)
- fInterceptor.write(b);
- else
- out.write(b);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/CommandInputFieldWithHistory.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/CommandInputFieldWithHistory.java
deleted file mode 100644
index 8ff47c9..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/CommandInputFieldWithHistory.java
+++ /dev/null
Binary files differ
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ICommandInputField.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ICommandInputField.java
deleted file mode 100644
index 4938a9f..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ICommandInputField.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control;
-
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.widgets.Composite;
-
-/**
- * Interface to create a command input control.
- *
- */
-public interface ICommandInputField {
- /**
- * @param parent
- * @param terminal
- */
- void createControl(Composite parent, ITerminalViewControl terminal);
-
- void dispose();
- /**
- * Sets the font of a control created with {@link #createControl(Composite, ITerminalViewControl)}
- * @param control
- * @param font the new text font
- */
- void setFont(Font font);
-
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ITerminalListener.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ITerminalListener.java
deleted file mode 100644
index 23adbff..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ITerminalListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control;
-
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-
-/**
- * Provided by a view implementation.
- * @author Michael Scharf
- *
- */
-public interface ITerminalListener {
- /**
- * Called when the state of the connection has changed.
- * @param state
- */
- void setState(TerminalState state);
-
- /**
- * Set the title of the terminal.
- * @param title
- */
- void setTerminalTitle(String title);
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ITerminalViewControl.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ITerminalViewControl.java
deleted file mode 100644
index dead1d5..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/ITerminalViewControl.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use
- ******************************************************************************/
-package org.eclipse.tm.internal.terminal.control;
-
-import java.io.UnsupportedEncodingException;
-
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.tm.internal.terminal.provisional.api.*;
-
-/**
- * @author Michael Scharf
- *
- */
-public interface ITerminalViewControl {
- /**
- * Set the encoding that the Terminal uses to decode byte streams into
- * characters.
- *
- * @see ITerminalControl#setEncoding(String)
- * @since org.eclipse.tm.terminal 2.0
- */
- void setEncoding(String encoding) throws UnsupportedEncodingException;
-
- /**
- * Get the Terminal's current encoding.
- *
- * @return the current Encoding of the Terminal.
- * @see ITerminalControl#getEncoding()
- * @since org.eclipse.tm.terminal 2.0
- */
- String getEncoding();
-
- boolean isEmpty();
- void setFont(Font font);
- void setInvertedColors(boolean invert);
- Font getFont();
- /**
- * @return the text control
- */
- Control getControl();
- /**
- * @return the root of all controls
- */
- Control getRootControl();
- boolean isDisposed();
- void selectAll();
- void clearTerminal();
- void copy();
- void paste();
- String getSelection();
- TerminalState getState();
- Clipboard getClipboard();
- void disconnectTerminal();
- void disposeTerminal();
- String getSettingsSummary();
- ITerminalConnector[] getConnectors();
- boolean setFocus();
- ITerminalConnector getTerminalConnector();
- void setConnector(ITerminalConnector connector);
- void connectTerminal();
- /**
- * @param write a single character to terminal
- */
- void sendKey(char arg0);
- /**
- * @param string write string to terminal
- */
- public boolean pasteString(String string);
-
- boolean isConnected();
-
- /**
- * @param inputField null means no input field is shown
- */
- void setCommandInputField(ICommandInputField inputField);
- /**
- * @return null or the current input field
- */
- ICommandInputField getCommandInputField();
-
- /**
- * @return the maximum number of lines to display
- * in the terminal view. -1 means unlimited.
- */
- public int getBufferLineLimit();
-
- /**
- * @param bufferLineLimit the maximum number of lines to show
- * in the terminal view. -1 means unlimited.
- */
- public void setBufferLineLimit(int bufferLineLimit);
- boolean isScrollLock();
- void setScrollLock(boolean on);
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/TerminalViewControlFactory.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/TerminalViewControlFactory.java
deleted file mode 100644
index 69e1195..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/TerminalViewControlFactory.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control;
-
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
-
-public class TerminalViewControlFactory {
- public static ITerminalViewControl makeControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
- return new VT100TerminalControl(target, wndParent, connectors);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/AbstractTerminalAction.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/AbstractTerminalAction.java
deleted file mode 100644
index 42ca60e..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/AbstractTerminalAction.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - Adapted from TerminalAction
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.resource.ImageRegistry;
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
-
-public abstract class AbstractTerminalAction extends Action {
- private final ITerminalViewControl fTarget;
-
- public AbstractTerminalAction(String strId) {
- this(null, strId, 0);
- }
-
- public AbstractTerminalAction(ITerminalViewControl target,
- String strId) {
- this(target, strId, 0);
- }
-
- public AbstractTerminalAction(ITerminalViewControl target,
- String strId, int style) {
- super("", style); //$NON-NLS-1$
-
- fTarget = target;
-
- setId(strId);
- }
-
- abstract public void run();
-
- protected void setupAction(String strText, String strToolTip,
- String strImage, String strEnabledImage, String strDisabledImage,
- boolean bEnabled) {
- setupAction(strText, strToolTip, strImage, strEnabledImage,
- strDisabledImage, bEnabled, TerminalPlugin.getDefault()
- .getImageRegistry());
- }
-
- protected void setupAction(String strText, String strToolTip,
- String strHoverImage, String strEnabledImage,
- String strDisabledImage, boolean bEnabled,
- ImageRegistry imageRegistry) {
- setupAction(strText, strToolTip, imageRegistry
- .getDescriptor(strHoverImage), imageRegistry
- .getDescriptor(strEnabledImage), imageRegistry
- .getDescriptor(strDisabledImage), bEnabled);
- }
-
- protected void setupAction(String strText, String strToolTip,
- ImageDescriptor hoverImage, ImageDescriptor enabledImage,
- ImageDescriptor disabledImage, boolean bEnabled) {
- setText(strText);
- setToolTipText(strToolTip);
- setEnabled(bEnabled);
- if (enabledImage != null) {
- setImageDescriptor(enabledImage);
- }
- if (disabledImage != null) {
- setDisabledImageDescriptor(disabledImage);
- }
- if (hoverImage != null) {
- setHoverImageDescriptor(hoverImage);
- }
- }
-
- /**
- * Return the terminal instance on which the action should operate.
- *
- * @return the terminal instance on which the action should operate.
- */
- protected ITerminalViewControl getTarget() {
- return fTarget;
- }
-
- /**
- * Subclasses can update their action
- *
- * @param aboutToShow true before the menu is shown -- false when the menu
- * gets hidden
- */
- public void updateAction(boolean aboutToShow) {
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ActionMessages.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ActionMessages.java
deleted file mode 100644
index 30a3091..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ActionMessages.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.osgi.util.NLS;
-
-public class ActionMessages extends NLS {
- static {
- NLS.initializeMessages(ActionMessages.class.getName(),
- ActionMessages.class);
- }
-
- public static String COPY;
- public static String CUT;
- public static String PASTE;
- public static String SELECTALL;
- public static String CLEARALL;
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ActionMessages.properties b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ActionMessages.properties
deleted file mode 100644
index 931a872..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ActionMessages.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-###############################################################################
-# Copyright (c) 2003, 2009 Wind River Systems, Inc. and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Initial Contributors:
-# The following Wind River employees contributed to the Terminal component
-# that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
-# Helmut Haigermoser and Ted Williams.
-#
-# Contributors:
-# Michael Scharf (Wind River) - split into core, view and connector plugins
-# Martin Oberhuber (Wind River) - fixed copyright headers and beautified
-# Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
-###############################################################################
-
-# NLS_MESSAGEFORMAT_NONE
-
-COPY = Copy
-CUT = Cut
-PASTE = Paste
-SELECTALL = Select All
-CLEARALL = Clear Terminal
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ImageConsts.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ImageConsts.java
deleted file mode 100644
index b69b669..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/ImageConsts.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - extracted from TerminalConsts
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-public interface ImageConsts {
- public final static String IMAGE_DIR_ROOT = "icons/"; //$NON-NLS-1$
- public final static String IMAGE_DIR_LOCALTOOL = IMAGE_DIR_ROOT + "clcl16/"; // basic colors - size 16x16 //$NON-NLS-1$
- public final static String IMAGE_DIR_DLCL = IMAGE_DIR_ROOT + "dlcl16/"; // disabled - size 16x16 //$NON-NLS-1$
- public final static String IMAGE_DIR_ELCL = IMAGE_DIR_ROOT+ "elcl16/"; // enabled - size 16x16 //$NON-NLS-1$
-
- public static final String IMAGE_CLCL_CLEAR_ALL = "ImageClclClearAll"; //$NON-NLS-1$
-
- public static final String IMAGE_DLCL_CLEAR_ALL = "ImageDlclClearAll"; //$NON-NLS-1$
-
- public static final String IMAGE_ELCL_CLEAR_ALL = "ImageElclClearAll"; //$NON-NLS-1$
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionClearAll.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionClearAll.java
deleted file mode 100644
index 65a4a3b..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionClearAll.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- * Uwe Stieber (Wind River) - [260372] [terminal] Certain terminal actions are enabled if no target terminal control is available
- ********************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-
-public class TerminalActionClearAll extends AbstractTerminalAction {
- public TerminalActionClearAll() {
- super(TerminalActionClearAll.class.getName());
-
- setupAction(ActionMessages.CLEARALL, ActionMessages.CLEARALL,
- ImageConsts.IMAGE_CLCL_CLEAR_ALL,
- ImageConsts.IMAGE_ELCL_CLEAR_ALL,
- ImageConsts.IMAGE_DLCL_CLEAR_ALL, false);
- }
-
- public TerminalActionClearAll(ITerminalViewControl target) {
- super(target, TerminalActionClearAll.class.getName());
-
- setupAction(ActionMessages.CLEARALL, ActionMessages.CLEARALL,
- ImageConsts.IMAGE_CLCL_CLEAR_ALL,
- ImageConsts.IMAGE_ELCL_CLEAR_ALL,
- ImageConsts.IMAGE_DLCL_CLEAR_ALL, false);
- }
-
- public void run() {
- ITerminalViewControl target = getTarget();
- if (target != null) {
- target.clearTerminal();
- }
- }
-
- public void updateAction(boolean aboutToShow) {
- ITerminalViewControl target = getTarget();
- setEnabled(target != null && !target.isEmpty());
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionCopy.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionCopy.java
deleted file mode 100644
index dabf91d..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionCopy.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- * Uwe Stieber (Wind River) - [260372] [terminal] Certain terminal actions are enabled if no target terminal control is available
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-
-public class TerminalActionCopy extends AbstractTerminalAction {
- public TerminalActionCopy() {
- super(TerminalActionCopy.class.getName());
- ISharedImages si = PlatformUI.getWorkbench().getSharedImages();
- setupAction(ActionMessages.COPY, ActionMessages.COPY, si
- .getImageDescriptor(ISharedImages.IMG_TOOL_COPY), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_COPY), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED), true);
- }
-
- public TerminalActionCopy(ITerminalViewControl target) {
- super(target, TerminalActionCopy.class.getName());
- ISharedImages si = PlatformUI.getWorkbench().getSharedImages();
- setupAction(ActionMessages.COPY, ActionMessages.COPY, si
- .getImageDescriptor(ISharedImages.IMG_TOOL_COPY), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_COPY), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED), true);
- }
-
- public void run() {
- ITerminalViewControl target = getTarget();
- if (target != null) {
- String selection = target.getSelection();
-
- if (!selection.equals("")) {//$NON-NLS-1$
- target.copy();
- } else {
- target.sendKey('\u0003');
- }
- }
- }
-
- public void updateAction(boolean aboutToShow) {
- ITerminalViewControl target = getTarget();
- boolean bEnabled = target != null;
- if (aboutToShow && bEnabled) {
- bEnabled = target.getSelection().length() > 0;
- }
- setEnabled(bEnabled);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionCut.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionCut.java
deleted file mode 100644
index b33d655..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionCut.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Uwe Stieber (Wind River) - [260372] [terminal] Certain terminal actions are enabled if no target terminal control is available
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-
-public class TerminalActionCut extends AbstractTerminalAction {
- public TerminalActionCut() {
- super(TerminalActionCut.class.getName());
- ISharedImages si = PlatformUI.getWorkbench().getSharedImages();
- setupAction(ActionMessages.CUT, ActionMessages.CUT, si
- .getImageDescriptor(ISharedImages.IMG_TOOL_CUT), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_CUT), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED), true);
- }
-
- public TerminalActionCut(ITerminalViewControl target) {
- super(target, TerminalActionCut.class.getName());
- ISharedImages si = PlatformUI.getWorkbench().getSharedImages();
- setupAction(ActionMessages.CUT, ActionMessages.CUT, si
- .getImageDescriptor(ISharedImages.IMG_TOOL_CUT), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_CUT), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED), true);
- }
-
- public void run() {
- ITerminalViewControl target = getTarget();
- if (target != null) {
- target.sendKey('\u0018');
- }
- }
-
- public void updateAction(boolean aboutToShow) {
- // Cut is always disabled
- setEnabled(false);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionPaste.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionPaste.java
deleted file mode 100644
index 3c33be2..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionPaste.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- * Uwe Stieber (Wind River) - [260372] [terminal] Certain terminal actions are enabled if no target terminal control is available
- * Uwe Stieber (Wind River) - [294719] [terminal] SWT Widget disposed in TerminalActionPaste
- * Martin Oberhuber (Wind River) - [296212] Cannot paste text into terminal on some Linux hosts
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-
-public class TerminalActionPaste extends AbstractTerminalAction {
- public TerminalActionPaste() {
- super(TerminalActionPaste.class.getName());
- ISharedImages si = PlatformUI.getWorkbench().getSharedImages();
- setupAction(ActionMessages.PASTE, ActionMessages.PASTE, si
- .getImageDescriptor(ISharedImages.IMG_TOOL_PASTE), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_PASTE), false);
- }
-
- public TerminalActionPaste(ITerminalViewControl target) {
- super(target, TerminalActionPaste.class.getName());
- ISharedImages si = PlatformUI.getWorkbench().getSharedImages();
- setupAction(ActionMessages.PASTE, ActionMessages.PASTE, si
- .getImageDescriptor(ISharedImages.IMG_TOOL_PASTE), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED), si
- .getImageDescriptor(ISharedImages.IMG_TOOL_PASTE), false);
- }
-
- public void run() {
- ITerminalViewControl target = getTarget();
- if (target != null) {
- target.paste();
- }
- }
-
- public void updateAction(boolean aboutToShow) {
- ITerminalViewControl target = getTarget();
- boolean bEnabled = target != null && target.getClipboard() != null && !target.getClipboard().isDisposed();
- if (bEnabled) {
- String strText = (String) target.getClipboard().getContents(
- TextTransfer.getInstance());
- bEnabled = ((strText != null) && (!strText.equals("")) && (target.getState() == TerminalState.CONNECTED));//$NON-NLS-1$
- }
- setEnabled(bEnabled);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionSelectAll.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionSelectAll.java
deleted file mode 100644
index 08526a8..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/actions/TerminalActionSelectAll.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- * Uwe Stieber (Wind River) - [260372] [terminal] Certain terminal actions are enabled if no target terminal control is available
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.actions;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-
-public class TerminalActionSelectAll extends AbstractTerminalAction {
- public TerminalActionSelectAll() {
- super(TerminalActionSelectAll.class.getName());
-
- setupAction(ActionMessages.SELECTALL, ActionMessages.SELECTALL,
- (ImageDescriptor) null, null, null, false);
- }
-
- public TerminalActionSelectAll(ITerminalViewControl target) {
- super(target, TerminalActionSelectAll.class.getName());
-
- setupAction(ActionMessages.SELECTALL, ActionMessages.SELECTALL,
- (ImageDescriptor) null, null, null, false);
- }
-
- public void run() {
- ITerminalViewControl target = getTarget();
- if (target != null) {
- target.selectAll();
- }
- }
-
- public void updateAction(boolean aboutToShow) {
- ITerminalViewControl target = getTarget();
- setEnabled(target != null && !target.isEmpty());
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java
deleted file mode 100644
index 52e65c5..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.impl;
-
-import java.io.OutputStream;
-
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-
-/**
- * need a better name!
- * @author Michael Scharf
- *
- */
-public interface ITerminalControlForText {
-
- TerminalState getState();
- void setState(TerminalState state);
- void setTerminalTitle(String title);
-
- ITerminalConnector getTerminalConnector();
-
- OutputStream getOutputStream();
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalInputStream.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalInputStream.java
deleted file mode 100644
index 8bcdf44..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalInputStream.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 1996, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Douglas Lea (Addison Wesley) - [cq:1552] BoundedBufferWithStateTracking adapted to BoundedByteBuffer
- *******************************************************************************/
-
-package org.eclipse.tm.internal.terminal.control.impl;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import org.eclipse.swt.widgets.Display;
-
-/**
- * The main purpose of this class is to start a runnable in the
- * display thread when data is available and to pretend no data
- * is available after a given amount of time the runnable is running.
- *
- */
-public class TerminalInputStream extends InputStream {
- /**
- * The maximum time in milliseconds the {@link #fNotifyChange} runs until
- * {@link #ready()} returns false.
- */
- private final int fUITimeout;
- /**
- * The output stream used by the terminal backend to write to the terminal
- */
- protected final OutputStream fOutputStream;
- /**
- * This runnable is called every time some characters are available from...
- */
- private final Runnable fNotifyChange;
- /**
- * A shared timer for all terminals. This times is used to limit the
- * time used in the display thread....
- */
- static Timer fgTimer=new Timer(false);
- /**
- * A blocking byte queue.
- */
- private final BoundedByteBuffer fQueue;
-
- /**
- * The maximum amount of data read and written in one shot.
- * The timer cannot interrupt reading this amount of data.
- * {@link #available()} and {@link #read(byte[], int, int)}
- * This is used as optimization, because reading single characters
- * can be very inefficient, because each call is synchronized.
- */
- // block size must be smaller than the Queue capacity!
- final int BLOCK_SIZE=64;
-
-
- /**
- * The runnable that is scheduled in the display tread. Takes care of the
- * timeout management. It calls the {@link #fNotifyChange}
- */
- // synchronized with fQueue!
- private Runnable fRunnable;
-
- /**
- * Used as flag to indicate that the current runnable
- * has used enough time in the display thread.
- * This variable is set by a timer thread after the
- * Runnable starts to run in the Display thread after
- * {@link #fUITimeout}.
- */
- // synchronized with fQueue!
- private boolean fEnoughDisplayTime;
-
- /**
- * A byte bounded buffer used to synchronize the input and the output stream.
- * <p>
- * Adapted from BoundedBufferWithStateTracking
- * http://gee.cs.oswego.edu/dl/cpj/allcode.java
- * http://gee.cs.oswego.edu/dl/cpj/
- * <p>
- * BoundedBufferWithStateTracking is part of the examples for the book
- * Concurrent Programming in Java: Design Principles and Patterns by
- * Doug Lea (ISBN 0-201-31009-0). Second edition published by
- * Addison-Wesley, November 1999. The code is
- * Copyright(c) Douglas Lea 1996, 1999 and released to the public domain
- * and may be used for any purposes whatsoever.
- * <p>
- * For some reasons a solution based on
- * PipedOutputStream/PipedIntputStream
- * does work *very* slowly:
- * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4404700
- * <p>
- *
- */
- class BoundedByteBuffer {
- protected final byte[] fBuffer; // the elements
- protected int fPutPos = 0; // circular indices
- protected int fTakePos = 0;
- protected int fUsedSlots = 0; // the count
- public BoundedByteBuffer(int capacity) throws IllegalArgumentException {
- // make sure we don't deadlock on too small capacity
- if(capacity<BLOCK_SIZE)
- capacity=2*BLOCK_SIZE;
- if (capacity <= 0)
- throw new IllegalArgumentException();
- fBuffer = new byte[capacity];
- }
- /**
- * @return the bytes available for {@link #read()}
- */
- public synchronized int size() {
- return fUsedSlots;
- }
- /**
- * Writes a single byte to the buffer. Blocks if the buffer is full.
- *
- * @param b the byte to write
- * @throws InterruptedException when the Thread is interrupted while
- * waiting for the buffer to become available because it was
- * full
- */
- public synchronized void write(byte b) throws InterruptedException {
- while (fUsedSlots == fBuffer.length)
- // wait until not full
- wait();
-
- fBuffer[fPutPos] = b;
- fPutPos = (fPutPos + 1) % fBuffer.length; // cyclically increment
-
- if (fUsedSlots++ == 0) // signal if was empty
- notifyAll();
- }
- /**
- * Read a single byte. Blocks until a byte is available.
- *
- * @return a byte from the buffer
- * @throws InterruptedException when the Thread is interrupted while
- * waiting for the buffer to be filled with a readable byte
- */
- public synchronized byte read() throws InterruptedException {
- while (fUsedSlots == 0)
- // wait until not empty
- wait();
- byte b = fBuffer[fTakePos];
- fTakePos = (fTakePos + 1) % fBuffer.length;
-
- if (fUsedSlots-- == fBuffer.length) // signal if was full
- notifyAll();
- return b;
- }
- }
-
- /**
- * An output stream that calls {@link TerminalInputStream#textAvailable}
- * every time data is written to the stream. The data is written to
- * {@link TerminalInputStream#fQueue}.
- *
- */
- class TerminalOutputStream extends OutputStream {
- public void write(byte[] b, int off, int len) throws IOException {
- try {
- // optimization to avoid many synchronized
- // sections: put the data in junks into the
- // queue.
- int noff=off;
- int end=off+len;
- while(noff<end) {
- int n=noff+BLOCK_SIZE;
- if(n>end)
- n=end;
- // now block the queue for the time we need to
- // add some characters
- synchronized(fQueue) {
- for(int i=noff;i<n;i++) {
- fQueue.write(b[i]);
- }
- bytesAreAvailable();
- }
- noff+=BLOCK_SIZE;
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- public void write(int b) throws IOException {
- try {
- // a kind of optimization, because
- // both calls use the fQueue lock...
- synchronized(fQueue) {
- fQueue.write((byte)b);
- bytesAreAvailable();
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- }
- /**
- * @param bufferSize the size of the buffer of the output stream
- * @param uiTimeout the maximum time the notifyChange runnable runs. It will be
- * rescheduled after uiTimeout if input data is still available.
- * @param notifyChange a Runnable that is posted to the Display thread
- * via {@link Display#asyncExec}. The runnable is posted several times!
- */
- public TerminalInputStream(int bufferSize,int uiTimeout,Runnable notifyChange) {
- //if(true) {notifyChange=new Runnable() {public void run() {byte buff[]=new byte[1024];while((available())>0)try {read(buff);} catch (IOException e) {break;}}};}
- fOutputStream =new TerminalOutputStream();
- fNotifyChange=notifyChange;
- fQueue=new BoundedByteBuffer(bufferSize);
- fUITimeout=uiTimeout;
- }
- /**
- * Posts the runnable {@link #fNotifyChange} to the display Thread,
- * unless the runnable is already scheduled.
- * It will make {@link #ready} return false after
- * {@link #fUITimeout} milli seconds.
- */
- void bytesAreAvailable() {
- // synchronize on the Queue to reduce the locks
- synchronized(fQueue) {
- if(fRunnable==null) {
- fRunnable=new Runnable(){
- public void run() {
- // protect the access to fRunnable
- synchronized(fQueue){
- fRunnable=null;
- }
- // end the reading after some time
- startTimer(fUITimeout);
- // and start the real runnable
- fNotifyChange.run();
- }
-
- };
- // TODO: make sure we don't create a display if the display is disposed...
- Display.getDefault().asyncExec(fRunnable);
- }
- }
-
- }
- /**
- * Starts a timer that sets {@link #fEnoughDisplayTime} to
- * true after milliSec.
- * @param milliSec The time after which fEnoughDisplayTime is set to true.
- */
- void startTimer(int milliSec) {
- synchronized(fQueue) {
- fEnoughDisplayTime=false;
- }
- fgTimer.schedule(new TimerTask(){
- public void run() {
- synchronized(fQueue) {
- fEnoughDisplayTime=true;
- // there is some data available
- if(fQueue.size()>0) {
- // schedule a new runnable to do the work
- bytesAreAvailable();
- }
- }
- }}, milliSec);
- }
- /**
- * @return the output stream used by the backend to write to the terminal.
- */
- public OutputStream getOutputStream() {
- return fOutputStream;
- }
- /**
- * Must be called in the Display Thread!
- * @return true if a character is available for the terminal to show.
- */
- public int available() {
- int available;
- synchronized(fQueue) {
- if(fEnoughDisplayTime)
- return 0;
- available=fQueue.size();
- }
- // Limit the available amount of data.
- // else our trick of limiting the time spend
- // reading might not work.
- if(available>BLOCK_SIZE)
- available=BLOCK_SIZE;
- return available;
- }
- /**
- * @return the next available byte. Check with {@link #available}
- * if characters are available.
- */
- public int read() throws IOException {
- try {
- return fQueue.read();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return -1;
- }
- }
- /**
- * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
- * this class can be called after the stream has been closed without
- * generating an <tt>IOException</tt>.
- * <p>
- */
- public void close() throws IOException {
- }
-
- public int read(byte[] cbuf, int off, int len) throws IOException {
- int n=0;
- // read as much as we can using a single synchronized statement
- synchronized (fQueue) {
- try {
- // The assumption is that the caller has used available to
- // check if bytes are available! That's why we don't check
- // for fEnoughDisplayTime!
- // Make sure that not more than BLOCK_SIZE is read in one call
- while(fQueue.size()>0 && n<len && n<BLOCK_SIZE) {
- cbuf[off+n]=fQueue.read();
- n++;
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- return n;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalMessages.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalMessages.java
deleted file mode 100644
index a54f02e..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalMessages.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.impl;
-
-import org.eclipse.osgi.util.NLS;
-
-public class TerminalMessages extends NLS {
- static {
- NLS.initializeMessages(TerminalMessages.class.getName(), TerminalMessages.class);
- }
-
- public static String TerminalError;
- public static String SocketError;
- public static String IOError;
- public static String CannotConnectTo;
- public static String NotInitialized;
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalMessages.properties b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalMessages.properties
deleted file mode 100644
index c77d4ee..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalMessages.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-###############################################################################
-# Copyright (c) 2003, 2009 Wind River Systems, Inc. and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Initial Contributors:
-# The following Wind River employees contributed to the Terminal component
-# that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
-# Helmut Haigermoser and Ted Williams.
-#
-# Contributors:
-# Michael Scharf (Wind River) - split into core, view and connector plugins
-# Martin Oberhuber (Wind River) - fixed copyright headers and beautified
-###############################################################################
-
-# NLS_MESSAGEFORMAT_VAR
-
-TerminalError = Terminal Error
-SocketError = Socket Error
-IOError = IO Error
-CannotConnectTo = Cannot initialize {0}:\n{1}
-NotInitialized = Not Initialized
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
deleted file mode 100644
index ce5940b..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/TerminalPlugin.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Anna Dushistova (MontaVista) - [227537] moved actions from terminal.view to terminal plugin
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.control.impl;
-
-import static org.eclipse.core.runtime.IStatus.ERROR;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.resource.ImageRegistry;
-import org.eclipse.tm.internal.terminal.control.actions.ImageConsts;
-import org.eclipse.tm.internal.terminal.provisional.api.Logger;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-
-public class TerminalPlugin extends AbstractUIPlugin {
- protected static TerminalPlugin fDefault;
- public static final String PLUGIN_ID = "org.eclipse.tm.terminal"; //$NON-NLS-1$
- public static final String HELP_VIEW = PLUGIN_ID + ".terminal_view"; //$NON-NLS-1$
-
- /**
- * The constructor.
- */
- public TerminalPlugin() {
- fDefault = this;
- }
- /**
- * Returns the shared instance.
- */
- public static TerminalPlugin getDefault() {
- return fDefault;
- }
-
- public static boolean isLogInfoEnabled() {
- return isOptionEnabled(Logger.TRACE_DEBUG_LOG_INFO);
- }
- public static boolean isLogErrorEnabled() {
- return isOptionEnabled(Logger.TRACE_DEBUG_LOG_ERROR);
- }
- public static boolean isLogEnabled() {
- return isOptionEnabled(Logger.TRACE_DEBUG_LOG);
- }
-
- public static boolean isOptionEnabled(String strOption) {
- String strEnabled = Platform.getDebugOption(strOption);
- if (strEnabled == null)
- return false;
-
- return new Boolean(strEnabled).booleanValue();
- }
-
- protected void initializeImageRegistry(ImageRegistry imageRegistry) {
- try {
- // Local toolbars
- putImageInRegistry(imageRegistry, ImageConsts.IMAGE_CLCL_CLEAR_ALL, ImageConsts.IMAGE_DIR_LOCALTOOL + "clear_co.gif"); //$NON-NLS-1$
- // Enabled local toolbars
- putImageInRegistry(imageRegistry, ImageConsts.IMAGE_ELCL_CLEAR_ALL, ImageConsts.IMAGE_DIR_ELCL + "clear_co.gif"); //$NON-NLS-1$
- // Disabled local toolbars
- putImageInRegistry(imageRegistry, ImageConsts.IMAGE_DLCL_CLEAR_ALL, ImageConsts.IMAGE_DIR_DLCL + "clear_co.gif"); //$NON-NLS-1$
- } catch (MalformedURLException malformedURLException) {
- malformedURLException.printStackTrace();
- }
- }
-
- protected void putImageInRegistry(ImageRegistry imageRegistry, String strKey, String relativePath) throws MalformedURLException {
- URL url = TerminalPlugin.getDefault().getBundle().getEntry(relativePath);
- ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(url);
- imageRegistry.put(strKey, imageDescriptor);
- }
-
- public static void log(String message, Exception error) {
- getDefault().getLog().log(new Status(ERROR, PLUGIN_ID, message, error));
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
deleted file mode 100644
index 2944b40..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/IVT100EmulatorBackend.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.emulator;
-
-import java.util.List;
-
-import org.eclipse.jface.text.hyperlink.IHyperlink;
-import org.eclipse.tm.terminal.model.Style;
-
-public interface IVT100EmulatorBackend {
-
- /**
- * This method erases all text from the Terminal view. Including the history
- */
- void clearAll();
-
- /**
- * Sets the Dimensions of the addressable scroll space of the screen....
- * Keeps the cursor position relative to the bottom of the screen!
- * @param lines
- * @param cols
- */
- void setDimensions(int lines, int cols);
-
- /**
- * This method makes room for N characters on the current line at the cursor
- * position. Text under the cursor moves right without wrapping at the end
- * of the line.
- * 01234
- * 0 123
- */
- void insertCharacters(int charactersToInsert);
-
- /**
- * Erases from cursor to end of screen, including cursor position. Cursor does not move.
- */
- void eraseToEndOfScreen();
-
- /**
- * Erases from beginning of screen to cursor, including cursor position. Cursor does not move.
- */
- void eraseToCursor();
-
- /**
- * Erases complete display. All lines are erased and changed to single-width. Cursor does not move.
- */
- void eraseAll();
-
- /**
- * Erases complete line.
- */
- void eraseLine();
-
- /**
- * Erases from cursor to end of line, including cursor position.
- */
- void eraseLineToEnd();
-
- /**
- * Erases from beginning of line to cursor, including cursor position.
- */
- void eraseLineToCursor();
-
- /**
- * Inserts n lines at line with cursor. Lines displayed below cursor move down.
- * Lines moved past the bottom margin are lost. This sequence is ignored when
- * cursor is outside scrolling region.
- * @param n the number of lines to insert
- */
- void insertLines(int n);
-
- /**
- * Deletes n characters, starting with the character at cursor position.
- * When a character is deleted, all characters to the right of cursor move
- * left. This creates a space character at right margin. This character
- * has same character attribute as the last character moved left.
- * @param n
- * 012345
- * 0145xx
- */
- void deleteCharacters(int n);
-
- /**
- * Deletes n lines, starting at line with cursor. As lines are deleted,
- * lines displayed below cursor move up. Lines added to bottom of screen
- * have spaces with same character attributes as last line moved up. This
- * sequence is ignored when cursor is outside scrolling region.
- * @param n the number of lines to delete
- */
- void deleteLines(int n);
-
- Style getDefaultStyle();
-
- void setDefaultStyle(Style defaultStyle);
-
- Style getStyle();
-
- /**
- * Sets the style to be used from now on
- * @param style
- */
- void setStyle(Style style);
-
- /**
- * This method displays a subset of the newly-received text in the Terminal
- * view, wrapping text at the right edge of the screen and overwriting text
- * when the cursor is not at the very end of the screen's text.
- * <p>
- *
- * There are never any ANSI control characters or escape sequences in the
- * text being displayed by this method (this includes newlines, carriage
- * returns, and tabs).
- * <p>
- */
- void appendString(String buffer);
-
- /**
- * Process a newline (Control-J) character. A newline (NL) character just
- * moves the cursor to the same column on the next line, creating new lines
- * when the cursor reaches the bottom edge of the terminal. This is
- * counter-intuitive, especially to UNIX programmers who are taught that
- * writing a single NL to a terminal is sufficient to move the cursor to the
- * first column of the next line, as if a carriage return (CR) and a NL were
- * written.
- * <p>
- *
- * UNIX terminals typically display a NL character as a CR followed by a NL
- * because the terminal device typically has the ONLCR attribute bit set
- * (see the termios(4) man page for details), which causes the terminal
- * device driver to translate NL to CR + NL on output. The terminal itself
- * (i.e., a hardware terminal or a terminal emulator, like xterm or this
- * code) _always_ interprets a CR to mean "move the cursor to the beginning
- * of the current line" and a NL to mean "move the cursor to the same column
- * on the next line".
- * <p>
- */
- void processNewline();
-
- /**
- * This method returns the relative line number of the line containing the
- * cursor. The returned line number is relative to the topmost visible line,
- * which has relative line number 0.
- *
- * @return The relative line number of the line containing the cursor.
- */
- int getCursorLine();
-
- int getCursorColumn();
-
- /**
- * This method moves the cursor to the specified line and column. Parameter
- * <i>targetLine</i> is the line number of a screen line, so it has a
- * minimum value of 0 (the topmost screen line) and a maximum value of
- * heightInLines - 1 (the bottommost screen line). A line does not have to
- * contain any text to move the cursor to any column in that line.
- */
- void setCursor(int targetLine, int targetColumn);
-
- void setCursorColumn(int targetColumn);
-
- void setCursorLine(int targetLine);
-
- int getLines();
-
- int getColumns();
-
- List<IHyperlink> hyperlinksAt(int line);
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/LoggingOutputStream.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/LoggingOutputStream.java
deleted file mode 100644
index b71c907..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/LoggingOutputStream.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.emulator;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.eclipse.tm.internal.terminal.provisional.api.Logger;
-
-public class LoggingOutputStream extends FilterOutputStream {
-
- public LoggingOutputStream(OutputStream out) {
- super(out);
- }
-
- public void write(byte[] b, int off, int len) throws IOException {
- if(Logger.isLogEnabled())
- Logger.log("Received " + len + " bytes: '" + //$NON-NLS-1$ //$NON-NLS-2$
- Logger.encode(new String(b, 0, len)) + "'"); //$NON-NLS-1$
-
- // we cannot call super.write, because this would call our write
- // which logs character by character.....
- //super.write(b, off, len);
- if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
- throw new IndexOutOfBoundsException();
-
- for (int i = 0 ; i < len ; i++) {
- super.write(b[off + i]);
- }
- }
-
- public void write(int b) throws IOException {
- if(Logger.isLogEnabled())
- Logger.log("Received " + 1 + " bytes: '" + //$NON-NLS-1$ //$NON-NLS-2$
- Logger.encode(new String(new byte[]{(byte)b}, 0, 1)) + "'"); //$NON-NLS-1$
- super.write(b);
- }
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
deleted file mode 100644
index 4140843..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100BackendTraceDecorator.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.emulator;
-
-import java.io.PrintStream;
-import java.util.List;
-
-import org.eclipse.jface.text.hyperlink.IHyperlink;
-import org.eclipse.tm.terminal.model.Style;
-
-public class VT100BackendTraceDecorator implements IVT100EmulatorBackend {
- final IVT100EmulatorBackend fBackend;
- final PrintStream fWriter;
- public VT100BackendTraceDecorator(IVT100EmulatorBackend backend, PrintStream out) {
- fBackend = backend;
- fWriter=out;
- }
-
- public void appendString(String buffer) {
- fWriter.println("appendString(\""+buffer+"\")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.appendString(buffer);
- }
-
- public void clearAll() {
- fWriter.println("clearAll()"); //$NON-NLS-1$
- fBackend.clearAll();
- }
-
- public void deleteCharacters(int n) {
- fWriter.println("deleteCharacters("+n+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.deleteCharacters(n);
- }
-
- public void deleteLines(int n) {
- fWriter.println("deleteLines("+n+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.deleteLines(n);
- }
-
- public void eraseAll() {
- fWriter.println("eraseAll()"); //$NON-NLS-1$
- fBackend.eraseAll();
- }
-
- public void eraseLine() {
- fWriter.println("eraseLine()"); //$NON-NLS-1$
- fBackend.eraseLine();
- }
-
- public void eraseLineToCursor() {
- fWriter.println("eraseLineToCursor()"); //$NON-NLS-1$
- fBackend.eraseLineToCursor();
- }
-
- public void eraseLineToEnd() {
- fWriter.println("eraseLineToEnd()"); //$NON-NLS-1$
- fBackend.eraseLineToEnd();
- }
-
- public void eraseToCursor() {
- fWriter.println("eraseToCursor()"); //$NON-NLS-1$
- fBackend.eraseToCursor();
- }
-
- public void eraseToEndOfScreen() {
- fWriter.println("eraseToEndOfScreen()"); //$NON-NLS-1$
- fBackend.eraseToEndOfScreen();
- }
-
- public int getColumns() {
- return fBackend.getColumns();
- }
-
- public int getCursorColumn() {
- return fBackend.getCursorColumn();
- }
-
- public int getCursorLine() {
- return fBackend.getCursorLine();
- }
-
- public Style getDefaultStyle() {
- return fBackend.getDefaultStyle();
- }
-
- public int getLines() {
- return fBackend.getLines();
- }
-
- public Style getStyle() {
- return fBackend.getStyle();
- }
-
- public void insertCharacters(int charactersToInsert) {
- fWriter.println("insertCharacters("+charactersToInsert+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.insertCharacters(charactersToInsert);
- }
-
- public void insertLines(int n) {
- fWriter.println("insertLines("+n+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.insertLines(n);
- }
-
- public void processNewline() {
- fWriter.println("processNewline()"); //$NON-NLS-1$
- fBackend.processNewline();
- }
-
- public void setCursor(int targetLine, int targetColumn) {
- fWriter.println("setCursor("+targetLine+", "+targetColumn+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- fBackend.setCursor(targetLine, targetColumn);
- }
-
- public void setCursorColumn(int targetColumn) {
- fWriter.println("setCursorColumn("+targetColumn+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.setCursorColumn(targetColumn);
- }
-
- public void setCursorLine(int targetLine) {
- fWriter.println("setCursorLine("+targetLine+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.setCursorLine(targetLine);
- }
-
- public void setDefaultStyle(Style defaultStyle) {
- fWriter.println("setDefaultStyle("+defaultStyle+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.setDefaultStyle(defaultStyle);
- }
-
- public void setDimensions(int lines, int cols) {
- fWriter.println("setDimensions("+lines+","+cols+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- fBackend.setDimensions(lines, cols);
- }
-
- public void setStyle(Style style) {
- fWriter.println("setStyle("+style+")"); //$NON-NLS-1$ //$NON-NLS-2$
- fBackend.setStyle(style);
- }
-
- @Override
- public List<IHyperlink> hyperlinksAt(int line) {
- return fBackend.hyperlinksAt(line);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
deleted file mode 100644
index c82c6b0..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java
+++ /dev/null
@@ -1,1197 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Michael Scharf (Wind River) - [209746] There are cases where some colors not displayed correctly
- * Martin Oberhuber (Wind River) - [168197] Fix Terminal for CDC-1.1/Foundation-1.1
- * Michael Scharf (Wind River) - [262996] get rid of TerminalState.OPENED
- * Martin Oberhuber (Wind River) - [334969] Fix multi-command SGR sequence
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.emulator;
-
-import java.io.*;
-import java.util.List;
-
-import org.eclipse.jface.text.hyperlink.IHyperlink;
-import org.eclipse.swt.events.*;
-import org.eclipse.tm.internal.terminal.control.impl.*;
-import org.eclipse.tm.internal.terminal.provisional.api.*;
-import org.eclipse.tm.terminal.model.*;
-
-/**
- * This class processes character data received from the remote host and
- * displays it to the user using the Terminal view's StyledText widget. This
- * class processes ANSI control characters, including NUL, backspace, carriage
- * return, linefeed, and a subset of ANSI escape sequences sufficient to allow
- * use of screen-oriented applications, such as vi, Emacs, and any GNU
- * readline-enabled application (Bash, bc, ncftp, etc.).
- * <p>
- *
- * @author Fran Litterio <francis.litterio@windriver.com>
- * @author Chris Thew <chris.thew@windriver.com>
- */
-public class VT100Emulator implements ControlListener {
- /** This is a character processing state: Initial state. */
- private static final int ANSISTATE_INITIAL = 0;
-
- /** This is a character processing state: We've seen an escape character. */
- private static final int ANSISTATE_ESCAPE = 1;
-
- /**
- * This is a character processing state: We've seen a '[' after an escape
- * character. Expecting a parameter character or a command character next.
- */
- private static final int ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND = 2;
-
- /**
- * This is a character processing state: We've seen a ']' after an escape
- * character. We are now expecting an operating system command that
- * reprograms an intelligent terminal.
- */
- private static final int ANSISTATE_EXPECTING_OS_COMMAND = 3;
-
- /**
- * This field holds the current state of the Finite TerminalState Automaton (FSA)
- * that recognizes ANSI escape sequences.
- *
- * @see #processNewText()
- */
- private int ansiState = ANSISTATE_INITIAL;
-
- /**
- * This field holds a reference to the {@link TerminalControl} object that
- * instantiates this class.
- */
- private final ITerminalControlForText terminal;
-
- /**
- * This field holds a reference to the StyledText widget that is used to
- * display text to the user.
- */
- final private IVT100EmulatorBackend text;
- /**
- * This field hold the saved absolute line number of the cursor when
- * processing the "ESC 7" and "ESC 8" command sequences.
- */
- private int savedCursorLine = 0;
-
- /**
- * This field hold the saved column number of the cursor when processing the
- * "ESC 7" and "ESC 8" command sequences.
- */
- private int savedCursorColumn = 0;
-
- /**
- * This field holds an array of StringBuffer objects, each of which is one
- * parameter from the current ANSI escape sequence. For example, when
- * parsing the escape sequence "\e[20;10H", this array holds the strings
- * "20" and "10".
- */
- private final StringBuffer[] ansiParameters = new StringBuffer[16];
-
- /**
- * This field holds the OS-specific command found in an escape sequence of
- * the form "\e]...\u0007".
- */
- private final StringBuffer ansiOsCommand = new StringBuffer(128);
-
- /**
- * This field holds the index of the next unused element of the array stored
- * in field {@link #ansiParameters}.
- */
- private int nextAnsiParameter = 0;
-
- Reader fReader;
-
- boolean fCrAfterNewLine;
- /**
- * The constructor.
- */
- public VT100Emulator(ITerminalTextData data, ITerminalControlForText terminal, Reader reader) {
- super();
-
- Logger.log("entered"); //$NON-NLS-1$
-
- this.terminal = terminal;
-
- for (int i = 0; i < ansiParameters.length; ++i) {
- ansiParameters[i] = new StringBuffer();
- }
- setInputStreamReader(reader);
- if(TerminalPlugin.isOptionEnabled("org.eclipse.tm.terminal/debug/log/VT100Backend")) {
- text=new VT100BackendTraceDecorator(new VT100EmulatorBackend(data),System.out);
- } else {
- text=new VT100EmulatorBackend(data);
- }
-
-// text.setDimensions(24, 80);
- Style style=Style.getStyle("BLACK", "WHITE"); //$NON-NLS-1$ //$NON-NLS-2$
- text.setDefaultStyle(style);
- text.setStyle(style);
- }
-
- /**
- * Set the reader that this Terminal gets its input from.
- *
- * The reader can be changed while the Terminal is running, but a change of
- * the reader likely loses some characters which have not yet been fully
- * read. Changing the reader can be done in order to change the selected
- * Encoding, though. This is typically done when the Terminal is
- * constructed, i.e. before it really starts operation; or, when the user
- * manually selects a different encoding and thus doesn't care about losing
- * old characters.
- *
- * @param reader the new Reader
- */
- public void setInputStreamReader(Reader reader) {
- fReader = reader;
- }
-
- public void setDimensions(int lines,int cols) {
- text.setDimensions(lines, cols);
- ITerminalConnector telnetConnection = getConnector();
- if (telnetConnection != null) {
- telnetConnection.setTerminalSize(text.getColumns(), text.getLines());
- }
-
- }
-
- /**
- * This method performs clean up when this VT100Emulator object is no longer
- * needed. After calling this method, no other method on this object should
- * be called.
- */
- public void dispose() {
- }
-
- /**
- * This method is required by interface ControlListener. It allows us to
- * know when the StyledText widget is moved.
- */
- @Override
- public void controlMoved(ControlEvent event) {
- Logger.log("entered"); //$NON-NLS-1$
- // Empty.
- }
-
- /**
- * This method is required by interface ControlListener. It allows us to
- * know when the StyledText widget is resized.
- */
- @Override
- public void controlResized(ControlEvent event) {
- Logger.log("entered"); //$NON-NLS-1$
- adjustTerminalDimensions();
- }
-
- /**
- * This method erases all text from the Terminal view.
- */
- public void clearTerminal() {
- Logger.log("entered"); //$NON-NLS-1$
- text.clearAll();
- }
-
- /**
- * This method is called when the user changes the Terminal view's font. We
- * attempt to recompute the pixel width of the new font's characters and fix
- * the terminal's dimensions.
- */
- public void fontChanged() {
- Logger.log("entered"); //$NON-NLS-1$
-
- if (text != null) {
- adjustTerminalDimensions();
- }
- }
-// /**
-// * This method executes in the Display thread to process data received from
-// * the remote host by class {@link org.eclipse.tm.internal.terminal.telnet.TelnetConnection} and
-// * other implementors of {@link ITerminalConnector}, like the
-// * SerialPortHandler.
-// * <p>
-// * These connectors write text to the terminal's buffer through
-// * {@link TerminalControl#writeToTerminal(String)} and then have
-// * this run method executed in the display thread. This method
-// * must not execute at the same time as methods
-// * {@link #setNewText(StringBuffer)} and {@link #clearTerminal()}.
-// * <p>
-// * IMPORTANT: This method must be called in strict alternation with method
-// * {@link #setNewText(StringBuffer)}.
-// * <p>
-// */
- public void processText() {
- try {
- // Find the width and height of the terminal, and resize it to display an
- // integral number of lines and columns.
-
- adjustTerminalDimensions();
-
- // Restore the caret offset, process and display the new text, then save
- // the caret offset. See the documentation for field caretOffset for
- // details.
-
- // ISSUE: Is this causing the scroll-to-bottom-on-output behavior?
-
- try {
- processNewText();
- } catch (IOException e) {
- Logger.logException(e);
- }
-
- } catch (Exception ex) {
- Logger.logException(ex);
- }
- }
- /**
- * This method scans the newly received text, processing ANSI control
- * characters and escape sequences and displaying normal text.
- * @throws IOException
- */
- private void processNewText() throws IOException {
- Logger.log("entered"); //$NON-NLS-1$
-
-
- // Scan the newly received text.
-
- while (hasNextChar()) {
- char character = getNextChar();
-
- switch (ansiState) {
- case ANSISTATE_INITIAL:
- switch (character) {
- case '\u0000':
- break; // NUL character. Ignore it.
-
- case '\u0007':
- processBEL(); // BEL (Control-G)
- break;
-
- case '\b':
- processBackspace(); // Backspace
- break;
-
- case '\t':
- processTab(); // Tab.
- break;
-
- case '\n':
- processNewline(); // Newline (Control-J)
- if(fCrAfterNewLine)
- {
- processCarriageReturn(); // Carriage Return (Control-M)
- }
- break;
-
- case '\r':
- processCarriageReturn(); // Carriage Return (Control-M)
- break;
-
- case '\u001b':
- ansiState = ANSISTATE_ESCAPE; // Escape.
- break;
-
- default:
- processNonControlCharacters(character);
- break;
- }
- break;
-
- case ANSISTATE_ESCAPE:
- // We've seen an escape character. Here, we process the character
- // immediately following the escape.
-
- switch (character) {
- case '[':
- ansiState = ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND;
- nextAnsiParameter = 0;
-
- // Erase the parameter strings in preparation for optional
- // parameter characters.
-
- for (int i = 0; i < ansiParameters.length; ++i) {
- ansiParameters[i].delete(0, ansiParameters[i].length());
- }
- break;
-
- case ']':
- ansiState = ANSISTATE_EXPECTING_OS_COMMAND;
- ansiOsCommand.delete(0, ansiOsCommand.length());
- break;
-
- case '7':
- // Save cursor position and character attributes
-
- ansiState = ANSISTATE_INITIAL;
- savedCursorLine = relativeCursorLine();
- savedCursorColumn = getCursorColumn();
- break;
-
- case '8':
- // Restore cursor and attributes to previously saved
- // position
-
- ansiState = ANSISTATE_INITIAL;
- moveCursor(savedCursorLine, savedCursorColumn);
- break;
-
- case 'c':
- // Reset the terminal
- ansiState = ANSISTATE_INITIAL;
- resetTerminal();
- break;
-
- default:
- Logger
- .log("Unsupported escape sequence: escape '" + character + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- ansiState = ANSISTATE_INITIAL;
- break;
- }
- break;
-
- case ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND:
- // Parameters can appear after the '[' in an escape sequence, but they
- // are optional.
-
- if (character == '@' || (character >= 'A' && character <= 'Z')
- || (character >= 'a' && character <= 'z')) {
- ansiState = ANSISTATE_INITIAL;
- processAnsiCommandCharacter(character);
- } else {
- processAnsiParameterCharacter(character);
- }
- break;
-
- case ANSISTATE_EXPECTING_OS_COMMAND:
- // A BEL (\u0007) character marks the end of the OSC sequence.
-
- if (character == '\u0007') {
- ansiState = ANSISTATE_INITIAL;
- processAnsiOsCommand();
- } else {
- ansiOsCommand.append(character);
- }
- break;
-
- default:
- // This should never happen! If it does happen, it means there is a
- // bug in the FSA. For robustness, we return to the initial
- // state.
-
- Logger.log("INVALID ANSI FSA STATE: " + ansiState); //$NON-NLS-1$
- ansiState = ANSISTATE_INITIAL;
- break;
- }
- }
- }
- private void resetTerminal() {
- text.eraseAll();
- text.setCursor(0, 0);
- text.setStyle(text.getDefaultStyle());
- }
- /**
- * This method is called when we have parsed an OS Command escape sequence.
- * The only one we support is "\e]0;...\u0007", which sets the terminal
- * title.
- */
- private void processAnsiOsCommand() {
- if (ansiOsCommand.charAt(0) != '0' || ansiOsCommand.charAt(1) != ';') {
- Logger
- .log("Ignoring unsupported ANSI OSC sequence: '" + ansiOsCommand + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- return;
- }
- terminal.setTerminalTitle(ansiOsCommand.substring(2));
- }
-
- /**
- * This method dispatches control to various processing methods based on the
- * command character found in the most recently received ANSI escape
- * sequence. This method only handles command characters that follow the
- * ANSI standard Control Sequence Introducer (CSI), which is "\e[...", where
- * "..." is an optional ';'-separated sequence of numeric parameters.
- * <p>
- */
- private void processAnsiCommandCharacter(char ansiCommandCharacter) {
- // If the width or height of the terminal is ridiculously small (one line or
- // column or less), don't even try to process the escape sequence. This avoids
- // throwing an exception (SPR 107450). The display will be messed up, but what
- // did you user expect by making the terminal so small?
-
- switch (ansiCommandCharacter) {
- case '@':
- // Insert character(s).
- processAnsiCommand_atsign();
- break;
-
- case 'A':
- // Move cursor up N lines (default 1).
- processAnsiCommand_A();
- break;
-
- case 'B':
- // Move cursor down N lines (default 1).
- processAnsiCommand_B();
- break;
-
- case 'C':
- // Move cursor forward N columns (default 1).
- processAnsiCommand_C();
- break;
-
- case 'D':
- // Move cursor backward N columns (default 1).
- processAnsiCommand_D();
- break;
-
- case 'E':
- // Move cursor to first column of Nth next line (default 1).
- processAnsiCommand_E();
- break;
-
- case 'F':
- // Move cursor to first column of Nth previous line (default 1).
- processAnsiCommand_F();
- break;
-
- case 'G':
- // Move to column N of current line (default 1).
- processAnsiCommand_G();
- break;
-
- case 'H':
- // Set cursor Position.
- processAnsiCommand_H();
- break;
-
- case 'J':
- // Erase part or all of display. Cursor does not move.
- processAnsiCommand_J();
- break;
-
- case 'K':
- // Erase in line (cursor does not move).
- processAnsiCommand_K();
- break;
-
- case 'L':
- // Insert line(s) (current line moves down).
- processAnsiCommand_L();
- break;
-
- case 'M':
- // Delete line(s).
- processAnsiCommand_M();
- break;
-
- case 'm':
- // Set Graphics Rendition (SGR).
- processAnsiCommand_m();
- break;
-
- case 'n':
- // Device Status Report (DSR).
- processAnsiCommand_n();
- break;
-
- case 'P':
- // Delete character(s).
- processAnsiCommand_P();
- break;
-
- case 'S':
- // Scroll up.
- // Emacs, vi, and GNU readline don't seem to use this command, so we ignore
- // it for now.
- break;
-
- case 'T':
- // Scroll down.
- // Emacs, vi, and GNU readline don't seem to use this command, so we ignore
- // it for now.
- break;
-
- case 'X':
- // Erase character.
- // Emacs, vi, and GNU readline don't seem to use this command, so we ignore
- // it for now.
- break;
-
- case 'Z':
- // Cursor back tab.
- // Emacs, vi, and GNU readline don't seem to use this command, so we ignore
- // it for now.
- break;
-
- default:
- Logger.log("Ignoring unsupported ANSI command character: '" + //$NON-NLS-1$
- ansiCommandCharacter + "'"); //$NON-NLS-1$
- break;
- }
- }
-
- /**
- * This method makes room for N characters on the current line at the cursor
- * position. Text under the cursor moves right without wrapping at the end
- * of the line.
- */
- private void processAnsiCommand_atsign() {
- int charactersToInsert = getAnsiParameter(0);
- text.insertCharacters(charactersToInsert);
- }
-
- /**
- * This method moves the cursor up by the number of lines specified by the
- * escape sequence parameter (default 1).
- */
- private void processAnsiCommand_A() {
- moveCursorUp(getAnsiParameter(0));
- }
-
- /**
- * This method moves the cursor down by the number of lines specified by the
- * escape sequence parameter (default 1).
- */
- private void processAnsiCommand_B() {
- moveCursorDown(getAnsiParameter(0));
- }
-
- /**
- * This method moves the cursor forward by the number of columns specified
- * by the escape sequence parameter (default 1).
- */
- private void processAnsiCommand_C() {
- moveCursorForward(getAnsiParameter(0));
- }
-
- /**
- * This method moves the cursor backward by the number of columns specified
- * by the escape sequence parameter (default 1).
- */
- private void processAnsiCommand_D() {
- moveCursorBackward(getAnsiParameter(0));
- }
-
- /**
- * This method moves the cursor to the first column of the Nth next line,
- * where N is specified by the ANSI parameter (default 1).
- */
- private void processAnsiCommand_E() {
- int linesToMove = getAnsiParameter(0);
-
- moveCursor(relativeCursorLine() + linesToMove, 0);
- }
-
- /**
- * This method moves the cursor to the first column of the Nth previous
- * line, where N is specified by the ANSI parameter (default 1).
- */
- private void processAnsiCommand_F() {
- int linesToMove = getAnsiParameter(0);
-
- moveCursor(relativeCursorLine() - linesToMove, 0);
- }
-
- /**
- * This method moves the cursor within the current line to the column
- * specified by the ANSI parameter (default is column 1).
- */
- private void processAnsiCommand_G() {
- int targetColumn = 1;
-
- if (ansiParameters[0].length() > 0) {
- targetColumn = getAnsiParameter(0) - 1;
- }
-
- moveCursor(relativeCursorLine(), targetColumn);
- }
-
- /**
- * This method sets the cursor to a position specified by the escape
- * sequence parameters (default is the upper left corner of the screen).
- */
- private void processAnsiCommand_H() {
- moveCursor(getAnsiParameter(0) - 1, getAnsiParameter(1) - 1);
- }
-
- /**
- * This method deletes some (or all) of the text on the screen without
- * moving the cursor.
- */
- private void processAnsiCommand_J() {
- int ansiParameter;
-
- if (ansiParameters[0].length() == 0) {
- ansiParameter = 0;
- } else {
- ansiParameter = getAnsiParameter(0);
- }
-
- switch (ansiParameter) {
- case 0:
- text.eraseToEndOfScreen();
- break;
-
- case 1:
- // Erase from beginning to current position (inclusive).
- text.eraseToCursor();
- break;
-
- case 2:
- // Erase entire display.
-
- text.eraseAll();
- break;
-
- default:
- Logger.log("Unexpected J-command parameter: " + ansiParameter); //$NON-NLS-1$
- break;
- }
- }
-
- /**
- * This method deletes some (or all) of the text in the current line without
- * moving the cursor.
- */
- private void processAnsiCommand_K() {
- int ansiParameter = getAnsiParameter(0);
-
- switch (ansiParameter) {
- case 0:
- // Erase from beginning to current position (inclusive).
- text.eraseLineToCursor();
- break;
-
- case 1:
- // Erase from current position to end (inclusive).
- text.eraseLineToEnd();
- break;
-
- case 2:
- // Erase entire line.
- text.eraseLine();
- break;
-
- default:
- Logger.log("Unexpected K-command parameter: " + ansiParameter); //$NON-NLS-1$
- break;
- }
- }
-
- /**
- * Insert one or more blank lines. The current line of text moves down. Text
- * that falls off the bottom of the screen is deleted.
- */
- private void processAnsiCommand_L() {
- text.insertLines(getAnsiParameter(0));
- }
-
- /**
- * Delete one or more lines of text. Any lines below the deleted lines move
- * up, which we implement by appending newlines to the end of the text.
- */
- private void processAnsiCommand_M() {
- text.deleteLines(getAnsiParameter(0));
- }
-
- /**
- * This method sets a new graphics rendition mode, such as
- * foreground/background color, bold/normal text, and reverse video.
- */
- private void processAnsiCommand_m() {
- if (ansiParameters[0].length() == 0) {
- // This a special case: when no ANSI parameter is specified, act like a
- // single parameter equal to 0 was specified.
-
- ansiParameters[0].append('0');
- }
- Style style=text.getStyle();
- // There are a non-zero number of ANSI parameters. Process each one in
- // order.
-
- int totalParameters = ansiParameters.length;
- int parameterIndex = 0;
-
- while (parameterIndex < totalParameters
- && ansiParameters[parameterIndex].length() > 0) {
- int ansiParameter = getAnsiParameter(parameterIndex);
-
- switch (ansiParameter) {
- case 0:
- // Reset all graphics modes.
- style = text.getDefaultStyle();
- break;
-
- case 1:
- style = style.setBold(true);
- break;
-
- case 4:
- style = style.setUnderline(true);
- break;
-
- case 5:
- style = style.setBlink(true);
- break;
-
- case 7:
- style = style.setReverse(true);
- break;
-
- case 10: // Set primary font. Ignored.
- break;
-
- case 21:
- case 22:
- style = style.setBold(false);
- break;
-
- case 24:
- style = style.setUnderline(false);
- break;
-
- case 25:
- style = style.setBlink(false);
- break;
-
- case 27:
- style = style.setReverse(false);
- break;
-
- case 30:
- style = style.setForground("BLACK"); //$NON-NLS-1$
- break;
-
- case 31:
- style = style.setForground("RED"); //$NON-NLS-1$
- break;
-
- case 32:
- style = style.setForground("GREEN"); //$NON-NLS-1$
- break;
-
- case 33:
- style = style.setForground("YELLOW"); //$NON-NLS-1$
- break;
-
- case 34:
- style = style.setForground("BLUE"); //$NON-NLS-1$
- break;
-
- case 35:
- style = style.setForground("MAGENTA"); //$NON-NLS-1$
- break;
-
- case 36:
- style = style.setForground("CYAN"); //$NON-NLS-1$
- break;
-
- case 37:
- style = style.setForground("WHITE_FOREGROUND"); //$NON-NLS-1$
- break;
-
- case 40:
- style = style.setBackground("BLACK"); //$NON-NLS-1$
- break;
-
- case 41:
- style = style.setBackground("RED"); //$NON-NLS-1$
- break;
-
- case 42:
- style = style.setBackground("GREEN"); //$NON-NLS-1$
- break;
-
- case 43:
- style = style.setBackground("YELLOW"); //$NON-NLS-1$
- break;
-
- case 44:
- style = style.setBackground("BLUE"); //$NON-NLS-1$
- break;
-
- case 45:
- style = style.setBackground("MAGENTA"); //$NON-NLS-1$
- break;
-
- case 46:
- style = style.setBackground("CYAN"); //$NON-NLS-1$
- break;
-
- case 47:
- style = style.setBackground("WHITE"); //$NON-NLS-1$
- break;
-
- default:
- Logger
- .log("Unsupported graphics rendition parameter: " + ansiParameter); //$NON-NLS-1$
- break;
- }
-
- ++parameterIndex;
- }
- text.setStyle(style);
- }
-
- /**
- * This method responds to an ANSI Device Status Report (DSR) command from
- * the remote endpoint requesting the cursor position. Requests for other
- * kinds of status are ignored.
- */
- private void processAnsiCommand_n() {
- // Do nothing if the numeric parameter was not 6 (which means report cursor
- // position).
-
- if (getAnsiParameter(0) != 6) {
- return;
- }
-
- // Send the ANSI cursor position (which is 1-based) to the remote endpoint.
-
- String positionReport = "\u001b[" + (relativeCursorLine() + 1) + ";" + //$NON-NLS-1$ //$NON-NLS-2$
- (getCursorColumn() + 1) + "R"; //$NON-NLS-1$
-
- try {
- OutputStreamWriter streamWriter = new OutputStreamWriter(terminal.getOutputStream(), "ISO-8859-1"); //$NON-NLS-1$
- streamWriter.write(positionReport, 0, positionReport.length());
- streamWriter.flush();
- } catch (IOException ex) {
- Logger.log("Caught IOException!"); //$NON-NLS-1$
- }
- }
-
- /**
- * Deletes one or more characters starting at the current cursor position.
- * Characters on the same line and to the right of the deleted characters
- * move left. If there are no characters on the current line at or to the
- * right of the cursor column, no text is deleted.
- */
- private void processAnsiCommand_P() {
- text.deleteCharacters(getAnsiParameter(0));
- }
-
- /**
- * This method returns one of the numeric ANSI parameters received in the
- * most recent escape sequence.
- *
- * @return The <i>parameterIndex</i>th numeric ANSI parameter or -1 if the
- * index is out of range.
- */
- private int getAnsiParameter(int parameterIndex) {
- if (parameterIndex < 0 || parameterIndex >= ansiParameters.length) {
- // This should never happen.
- return -1;
- }
-
- String parameter = ansiParameters[parameterIndex].toString();
-
- if (parameter.length() == 0) {
- return 1;
- }
-
- int parameterValue = 1;
-
- // Don't trust the remote endpoint to send well formed numeric
- // parameters.
-
- try {
- parameterValue = Integer.parseInt(parameter);
- } catch (NumberFormatException ex) {
- parameterValue = 1;
- }
-
- return parameterValue;
- }
-
- /**
- * This method processes a single parameter character in an ANSI escape
- * sequence. Parameters are the (optional) characters between the leading
- * "\e[" and the command character in an escape sequence (e.g., in the
- * escape sequence "\e[20;10H", the parameter characters are "20;10").
- * Parameters are integers separated by one or more ';'s.
- */
- private void processAnsiParameterCharacter(char ch) {
- if (ch == ';') {
- ++nextAnsiParameter;
- } else {
- if (nextAnsiParameter < ansiParameters.length) {
- ansiParameters[nextAnsiParameter].append(ch);
- }
- }
- }
- /**
- * This method processes a contiguous sequence of non-control characters.
- * This is a performance optimization, so that we don't have to insert or
- * append each non-control character individually to the StyledText widget.
- * A non-control character is any character that passes the condition in the
- * below while loop.
- * @throws IOException
- */
- private void processNonControlCharacters(char character) throws IOException {
- StringBuffer buffer=new StringBuffer();
- buffer.append(character);
- // Identify a contiguous sequence of non-control characters, starting at
- // firstNonControlCharacterIndex in newText.
- while(hasNextChar()) {
- character=getNextChar();
- if(character == '\u0000' || character == '\b' || character == '\t'
- || character == '\u0007' || character == '\n'
- || character == '\r' || character == '\u001b') {
- pushBackChar(character);
- break;
- }
- buffer.append(character);
- }
-
- // Now insert the sequence of non-control characters in the StyledText widget
- // at the location of the cursor.
-
- displayNewText(buffer.toString());
- }
-
- /**
- * This method displays a subset of the newly-received text in the Terminal
- * view, wrapping text at the right edge of the screen and overwriting text
- * when the cursor is not at the very end of the screen's text.
- * <p>
- *
- * There are never any ANSI control characters or escape sequences in the
- * text being displayed by this method (this includes newlines, carriage
- * returns, and tabs).
- * <p>
- */
- private void displayNewText(String buffer) {
- text.appendString(buffer);
- }
-
-
- /**
- * Process a BEL (Control-G) character.
- */
- private void processBEL() {
- // TODO
- //Display.getDefault().beep();
- }
-
- /**
- * Process a backspace (Control-H) character.
- */
- private void processBackspace() {
- moveCursorBackward(1);
- }
-
- /**
- * Process a tab (Control-I) character. We don't insert a tab character into
- * the StyledText widget. Instead, we move the cursor forward to the next
- * tab stop, without altering any of the text. Tab stops are every 8
- * columns. The cursor will never move past the rightmost column.
- */
- private void processTab() {
- moveCursorForward(8 - (getCursorColumn() % 8));
- }
-
- /**
- * Process a newline (Control-J) character. A newline (NL) character just
- * moves the cursor to the same column on the next line, creating new lines
- * when the cursor reaches the bottom edge of the terminal. This is
- * counter-intuitive, especially to UNIX programmers who are taught that
- * writing a single NL to a terminal is sufficient to move the cursor to the
- * first column of the next line, as if a carriage return (CR) and a NL were
- * written.
- * <p>
- *
- * UNIX terminals typically display a NL character as a CR followed by a NL
- * because the terminal device typically has the ONLCR attribute bit set
- * (see the termios(4) man page for details), which causes the terminal
- * device driver to translate NL to CR + NL on output. The terminal itself
- * (i.e., a hardware terminal or a terminal emulator, like xterm or this
- * code) _always_ interprets a CR to mean "move the cursor to the beginning
- * of the current line" and a NL to mean "move the cursor to the same column
- * on the next line".
- * <p>
- */
- private void processNewline() {
- text.processNewline();
- }
-
- /**
- * Process a Carriage Return (Control-M).
- */
- private void processCarriageReturn() {
- text.setCursorColumn(0);
- }
-
- /**
- * This method computes the width of the terminal in columns and its height
- * in lines, then adjusts the width and height of the view's StyledText
- * widget so that it displays an integral number of lines and columns of
- * text. The adjustment is always to shrink the widget vertically or
- * horizontally, because if the control were to grow, it would be clipped by
- * the edges of the view window (i.e., the view window does not become
- * larger to accommodate its contents becoming larger).
- * <p>
- *
- * This method must be called immediately before each time text is written
- * to the terminal so that we can properly line wrap text. Because it is
- * called so frequently, it must be fast when there is no resizing to be
- * done.
- * <p>
- */
- private void adjustTerminalDimensions() {
- // Compute how many pixels we need to shrink the StyledText control vertically
- // to make it display an integral number of lines of text.
-
- // TODO
-// if(text.getColumns()!=80 && text.getLines()!=80)
-// text.setDimensions(24, 80);
- // If we are in a TELNET connection and we know the dimensions of the terminal,
- // we give the size information to the TELNET connection object so it can
- // communicate it to the TELNET server. If we are in a serial connection,
- // there is nothing we can do to tell the remote host about the size of the
- // terminal.
- ITerminalConnector telnetConnection = getConnector();
- // TODO MSA: send only if dimensions have really changed!
- if (telnetConnection != null) {
- telnetConnection.setTerminalSize(text.getColumns(), text.getLines());
- }
-
- }
-
- private ITerminalConnector getConnector() {
- if(terminal.getTerminalConnector()!=null) {
- return terminal.getTerminalConnector();
- }
- return null;
- }
-
- /**
- * This method returns the relative line number of the line containing the
- * cursor. The returned line number is relative to the topmost visible line,
- * which has relative line number 0.
- *
- * @return The relative line number of the line containing the cursor.
- */
- private int relativeCursorLine() {
- return text.getCursorLine();
- }
-
- /**
- * This method moves the cursor to the specified line and column. Parameter
- * <i>targetLine</i> is the line number of a screen line, so it has a
- * minimum value of 0 (the topmost screen line) and a maximum value of
- * heightInLines - 1 (the bottommost screen line). A line does not have to
- * contain any text to move the cursor to any column in that line.
- */
- private void moveCursor(int targetLine, int targetColumn) {
- text.setCursor(targetLine,targetColumn);
- }
-
- /**
- * This method moves the cursor down <i>lines</i> lines, but won't move the
- * cursor past the bottom of the screen. This method does not cause any
- * scrolling.
- */
- private void moveCursorDown(int lines) {
- moveCursor(relativeCursorLine() + lines, getCursorColumn());
- }
-
- /**
- * This method moves the cursor up <i>lines</i> lines, but won't move the
- * cursor past the top of the screen. This method does not cause any
- * scrolling.
- */
- private void moveCursorUp(int lines) {
- moveCursor(relativeCursorLine() - lines, getCursorColumn());
- }
-
- /**
- * This method moves the cursor forward <i>columns</i> columns, but won't
- * move the cursor past the right edge of the screen, nor will it move the
- * cursor onto the next line. This method does not cause any scrolling.
- */
- private void moveCursorForward(int columnsToMove) {
- moveCursor(relativeCursorLine(), getCursorColumn() + columnsToMove);
- }
-
- /**
- * This method moves the cursor backward <i>columnsToMove</i> columns, but
- * won't move the cursor past the left edge of the screen, nor will it move
- * the cursor onto the previous line. This method does not cause any
- * scrolling.
- */
- private void moveCursorBackward(int columnsToMove) {
- moveCursor(relativeCursorLine(), getCursorColumn() - columnsToMove);
- }
- /**
- * Resets the state of the terminal text (foreground color, background color,
- * font style and other internal state). It essentially makes it ready for new input.
- */
- public void resetState() {
- ansiState=ANSISTATE_INITIAL;
- text.setStyle(text.getDefaultStyle());
- }
-
-// public OutputStream getOutputStream() {
-// return fTerminalInputStream.getOutputStream();
-// }
-
- /**
- * Buffer for {@link #pushBackChar(char)}.
- */
- private int fNextChar=-1;
- private char getNextChar() throws IOException {
- int c=-1;
- if(fNextChar!=-1) {
- c= fNextChar;
- fNextChar=-1;
- } else {
- c = fReader.read();
- }
- // TODO: better end of file handling
- if(c==-1) {
- c=0;
- }
- return (char)c;
- }
-
- private boolean hasNextChar() throws IOException {
- if(fNextChar>=0) {
- return true;
- }
- return fReader.ready();
- }
-
- /**
- * Put back one character to the stream. This method can push
- * back exactly one character. The character is the next character
- * returned by {@link #getNextChar}
- * @param c the character to be pushed back.
- */
- void pushBackChar(char c) {
- //assert fNextChar!=-1: "Already a character waiting:"+fNextChar; //$NON-NLS-1$
- fNextChar=c;
- }
- private int getCursorColumn() {
- return text.getCursorColumn();
- }
- public boolean isCrAfterNewLine() {
- return fCrAfterNewLine;
- }
- public void setCrAfterNewLine(boolean crAfterNewLine) {
- fCrAfterNewLine = crAfterNewLine;
- }
-
- public List<IHyperlink> hyperlinksAt(int line) {
- return text.hyperlinksAt(line);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
deleted file mode 100644
index a31ab2a..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorBackend.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Anton Leherbauer (Wind River) - [206329] Changing terminal size right after connect does not scroll properly
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.emulator;
-
-import static java.util.Collections.emptyList;
-
-import java.util.*;
-
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.hyperlink.IHyperlink;
-import org.eclipse.tm.terminal.model.*;
-
-import com.google.eclipse.terminal.ui.hyperlink.*;
-
-/**
- *
- */
-public class VT100EmulatorBackend implements IVT100EmulatorBackend {
-
- /**
- * This field holds the number of the column in which the cursor is
- * logically positioned. The leftmost column on the screen is column 0, and
- * column numbers increase to the right. The maximum value of this field is
- * {@link #widthInColumns} - 1. We track the cursor column using this field
- * to avoid having to recompute it repeatly using StyledText method calls.
- * <p>
- *
- * The StyledText widget that displays text has a vertical bar (called the
- * "caret") that appears _between_ character cells, but ANSI terminals have
- * the concept of a cursor that appears _in_ a character cell, so we need a
- * convention for which character cell the cursor logically occupies when
- * the caret is physically between two cells. The convention used in this
- * class is that the cursor is logically in column N when the caret is
- * physically positioned immediately to the _left_ of column N.
- * <p>
- *
- * When fCursorColumn is N, the next character output to the terminal appears
- * in column N. When a character is output to the rightmost column on a
- * given line (column widthInColumns - 1), the cursor moves to column 0 on
- * the next line after the character is drawn (this is how line wrapping is
- * implemented). If the cursor is in the bottommost line when line wrapping
- * occurs, the topmost visible line is scrolled off the top edge of the
- * screen.
- * <p>
- */
- private int fCursorColumn;
- private int fCursorLine;
- private Style fDefaultStyle;
- private Style fStyle;
- int fLines;
- int fColumns;
- final private ITerminalTextData fTerminal;
-
- private final IHyperlinkFactory urlHyperlinkFactory = new HttpHyperlinkFactory();
- private final Map<Integer, List<IHyperlink>> hyperlinks = new HashMap<Integer, List<IHyperlink>>();
-
- public VT100EmulatorBackend(ITerminalTextData terminal) {
- fTerminal=terminal;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#clearAll()
- */
- public void clearAll() {
- synchronized (fTerminal) {
- // clear the history
- int n=fTerminal.getHeight();
- for (int line = 0; line < n; line++) {
- fTerminal.cleanLine(line);
- }
- fTerminal.setDimensions(fLines, fTerminal.getWidth());
- setStyle(getDefaultStyle());
- setCursor(0, 0);
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setDimensions(int, int)
- */
- public void setDimensions(int lines, int cols) {
- synchronized (fTerminal) {
- if(lines==fLines && cols==fColumns)
- {
- return; // nothing to do
- }
- // relative cursor line
- int cl=getCursorLine();
- int cc=getCursorColumn();
- int height=fTerminal.getHeight();
- // absolute cursor line
- int acl=cl+height-fLines;
- int newLines=Math.max(lines,height);
- if(lines<fLines) {
- if(height==fLines) {
- // if the terminal has no history, then resize by
- // setting the size to the new size
- // TODO We are assuming that cursor line points at end of text
- newLines=Math.max(lines, cl+1);
- }
- }
- fLines=lines;
- fColumns=cols;
- // make the terminal at least as high as we need lines
- fTerminal.setDimensions(newLines, fColumns);
- // compute relative cursor line
- cl=acl-(newLines-fLines);
- setCursor(cl, cc);
- }
- }
-
- int toAbsoluteLine(int line) {
- synchronized (fTerminal) {
- return fTerminal.getHeight()-fLines+line;
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#insertCharacters(int)
- */
- public void insertCharacters(int charactersToInsert) {
- synchronized (fTerminal) {
- int line=toAbsoluteLine(fCursorLine);
- int n=charactersToInsert;
- for (int col = fColumns-1; col >=fCursorColumn+n; col--) {
- char c=fTerminal.getChar(line, col-n);
- Style style=fTerminal.getStyle(line, col-n);
- fTerminal.setChar(line, col,c, style);
- }
- int last=Math.min(fCursorColumn+n, fColumns);
- for (int col = fCursorColumn; col <last; col++) {
- fTerminal.setChar(line, col,'\000', null);
- }
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseToEndOfScreen()
- */
- public void eraseToEndOfScreen() {
- synchronized (fTerminal) {
- eraseLineToEnd();
- for (int line = toAbsoluteLine(fCursorLine+1); line < toAbsoluteLine(fLines); line++) {
- fTerminal.cleanLine(line);
- }
- }
-
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseToCursor()
- */
- public void eraseToCursor() {
- synchronized (fTerminal) {
- for (int line = toAbsoluteLine(0); line < toAbsoluteLine(fCursorLine); line++) {
- fTerminal.cleanLine(line);
- }
- eraseLineToCursor();
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseAll()
- */
- public void eraseAll() {
- synchronized (fTerminal) {
- for (int line = toAbsoluteLine(0); line < toAbsoluteLine(fLines); line++) {
- fTerminal.cleanLine(line);
- }
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseLine()
- */
- public void eraseLine() {
- synchronized (fTerminal) {
- fTerminal.cleanLine(toAbsoluteLine(fCursorLine));
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseLineToEnd()
- */
- public void eraseLineToEnd() {
- synchronized (fTerminal) {
- int line=toAbsoluteLine(fCursorLine);
- for (int col = fCursorColumn; col < fColumns; col++) {
- fTerminal.setChar(line, col, '\000', null);
- }
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#eraseLineToCursor()
- */
- @Override
- public void eraseLineToCursor() {
- synchronized (fTerminal) {
- int line=toAbsoluteLine(fCursorLine);
- for (int col = 0; col <= fCursorColumn; col++) {
- fTerminal.setChar(line, col, '\000', null);
- }
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#insertLines(int)
- */
- @Override
- public void insertLines(int n) {
- synchronized (fTerminal) {
- if(!isCusorInScrollingRegion()) {
- return;
- }
- assert n>0;
- int line=toAbsoluteLine(fCursorLine);
- int nLines=fTerminal.getHeight()-line;
- fTerminal.scroll(line, nLines, n);
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#deleteCharacters(int)
- */
- public void deleteCharacters(int n) {
- synchronized (fTerminal) {
- int line=toAbsoluteLine(fCursorLine);
- for (int col = fCursorColumn+n; col < fColumns; col++) {
- char c=fTerminal.getChar(line, col);
- Style style=fTerminal.getStyle(line, col);
- fTerminal.setChar(line, col-n,c, style);
- }
- int first=Math.max(fCursorColumn, fColumns-n);
- for (int col = first; col <fColumns; col++) {
- fTerminal.setChar(line, col,'\000', null);
- }
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#deleteLines(int)
- */
- @Override
- public void deleteLines(int n) {
- synchronized (fTerminal) {
- if(!isCusorInScrollingRegion()) {
- return;
- }
- assert n>0;
- int line=toAbsoluteLine(fCursorLine);
- int nLines=fTerminal.getHeight()-line;
- fTerminal.scroll(line, nLines, -n);
- }
- }
- private boolean isCusorInScrollingRegion() {
- // TODO Auto-generated method stub
- return true;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getDefaultStyle()
- */
- public Style getDefaultStyle() {
- synchronized (fTerminal) {
- return fDefaultStyle;
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setDefaultStyle(org.eclipse.tm.terminal.model.Style)
- */
- public void setDefaultStyle(Style defaultStyle) {
- synchronized (fTerminal) {
- fDefaultStyle = defaultStyle;
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getStyle()
- */
- public Style getStyle() {
- synchronized (fTerminal) {
- if(fStyle==null) {
- return fDefaultStyle;
- }
- return fStyle;
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setStyle(org.eclipse.tm.terminal.model.Style)
- */
- public void setStyle(Style style) {
- synchronized (fTerminal) {
- fStyle=style;
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#appendString(java.lang.String)
- */
- public void appendString(String buffer) {
- synchronized (fTerminal) {
- char[] chars=buffer.toCharArray();
- int line=toAbsoluteLine(fCursorLine);
- int originalLine = line;
- List<IHyperlink> found = emptyList();
- if (buffer != null) {
- found = urlHyperlinkFactory.hyperlinksIn(fCursorColumn, buffer);
- hyperlinks.put(new Integer(line), found);
- }
- int i=0;
- while (i < chars.length) {
- int n=Math.min(fColumns-fCursorColumn,chars.length-i);
- fTerminal.setChars(line, fCursorColumn, chars, i, n, fStyle);
- int col=fCursorColumn+n;
- i+=n;
- // wrap needed?
- if(col>=fColumns) {
- doNewline();
- line=toAbsoluteLine(fCursorLine);
- setCursorColumn(0);
- } else {
- setCursorColumn(col);
- }
- }
- drawHyperlinks(found, originalLine);
- }
- }
-
- private void drawHyperlinks(List<IHyperlink> hyperlinks, int line) {
- for (IHyperlink hyperlink : hyperlinks) {
- IRegion region = hyperlink.getHyperlinkRegion();
- int start = region.getOffset();
- int end = start + region.getLength();
- for (int column = start; column < end; column++) {
- Style style = fTerminal.getStyle(line, column);
- if (style != null) {
- style = style.setUnderline(true);
- fTerminal.setChar(line, column, fTerminal.getChar(line, column), style);
- }
- }
- }
- }
-
- /**
- * MUST be called from a synchronized block!
- */
- private void doNewline() {
- if(fCursorLine+1>=fLines) {
- int h=fTerminal.getHeight();
- fTerminal.addLine();
- if(h!=fTerminal.getHeight()) {
- setCursorLine(fCursorLine+1);
- }
- } else {
- setCursorLine(fCursorLine+1);
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#processNewline()
- */
- public void processNewline() {
- synchronized (fTerminal) {
- doNewline();
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getCursorLine()
- */
- public int getCursorLine() {
- synchronized (fTerminal) {
- return fCursorLine;
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getCursorColumn()
- */
- public int getCursorColumn() {
- synchronized (fTerminal) {
- return fCursorColumn;
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setCursor(int, int)
- */
- public void setCursor(int targetLine, int targetColumn) {
- synchronized (fTerminal) {
- setCursorLine(targetLine);
- setCursorColumn(targetColumn);
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setCursorColumn(int)
- */
- public void setCursorColumn(int targetColumn) {
- synchronized (fTerminal) {
- if(targetColumn<0) {
- targetColumn=0;
- } else if(targetColumn>=fColumns) {
- targetColumn=fColumns-1;
- }
- fCursorColumn=targetColumn;
- // We make the assumption that nobody is changing the
- // terminal cursor except this class!
- // This assumption gives a huge performance improvement
- fTerminal.setCursorColumn(targetColumn);
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#setCursorLine(int)
- */
- public void setCursorLine(int targetLine) {
- synchronized (fTerminal) {
- if(targetLine<0) {
- targetLine=0;
- } else if(targetLine>=fLines) {
- targetLine=fLines-1;
- }
- fCursorLine=targetLine;
- // We make the assumption that nobody is changing the
- // terminal cursor except this class!
- // This assumption gives a huge performance improvement
- fTerminal.setCursorLine(toAbsoluteLine(targetLine));
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getLines()
- */
- public int getLines() {
- synchronized (fTerminal) {
- return fLines;
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.emulator.IVT100EmulatorBackend#getColumns()
- */
- public int getColumns() {
- synchronized (fTerminal) {
- return fColumns;
- }
- }
-
- public List<IHyperlink> hyperlinksAt(int line) {
- List<IHyperlink> found = hyperlinks.get(new Integer(line));
- if (found == null) {
- return emptyList();
- }
- return found;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
deleted file mode 100644
index ed1039b..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
+++ /dev/null
@@ -1,1111 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following Wind River employees contributed to the Terminal component
- * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
- * Helmut Haigermoser and Ted Williams.
- *
- * Contributors:
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Martin Oberhuber (Wind River) - [206892] State handling: Only allow connect when CLOSED
- * Martin Oberhuber (Wind River) - [206883] Serial Terminal leaks Jobs
- * Martin Oberhuber (Wind River) - [208145] Terminal prints garbage after quick disconnect/reconnect
- * Martin Oberhuber (Wind River) - [207785] NPE when trying to send char while no longer connected
- * Michael Scharf (Wind River) - [209665] Add ability to log byte streams from terminal
- * Ruslan Sychev (Xored Software) - [217675] NPE or SWTException when closing Terminal View while connection establishing
- * Michael Scharf (Wing River) - [196447] The optional terminal input line should be resizeable
- * Martin Oberhuber (Wind River) - [168197] Replace JFace MessagDialog by SWT MessageBox
- * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use
- * Michael Scharf (Wind River) - [237398] Terminal get Invalid Thread Access when the title is set
- * Martin Oberhuber (Wind River) - [240745] Pressing Ctrl+F1 in the Terminal should bring up context help
- * Michael Scharf (Wind River) - [240098] The cursor should not blink when the terminal is disconnected
- * Anton Leherbauer (Wind River) - [335021] Middle mouse button copy/paste does not work with the terminal
- * Max Stepanov (Appcelerator) - [339768] Fix ANSI code for PgUp / PgDn
- * Pawel Piech (Wind River) - [333613] "Job found still running" after shutdown
- * Martin Oberhuber (Wind River) - [348700] Terminal unusable after disconnect
- * Simon Bernard (Sierra Wireless) - [351424] [terminal] Terminal does not support del and insert key
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.emulator;
-
-import static org.eclipse.jface.bindings.keys.SWTKeySupport.convertEventToUnmodifiedAccelerator;
-
-import java.io.*;
-import java.net.SocketException;
-import java.util.List;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.hyperlink.IHyperlink;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
-import org.eclipse.tm.internal.terminal.control.*;
-import org.eclipse.tm.internal.terminal.control.impl.*;
-import org.eclipse.tm.internal.terminal.provisional.api.*;
-import org.eclipse.tm.internal.terminal.textcanvas.*;
-import org.eclipse.tm.internal.terminal.textcanvas.PipedInputStream;
-import org.eclipse.tm.terminal.model.*;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.contexts.*;
-import org.eclipse.ui.keys.IBindingService;
-
-/**
- *
- * This class was originally written to use nested classes, which unfortunately makes
- * this source file larger and more complex than it needs to be. In particular, the
- * methods in the nested classes directly access the fields of the enclosing class.
- * One day we should pull the nested classes out into their own source files (but still
- * in this package).
- *
- * @author Chris Thew <chris.thew@windriver.com>
- */
-public class VT100TerminalControl implements ITerminalControlForText, ITerminalControl, ITerminalViewControl
-{
- protected final static String[] LINE_DELIMITERS = { "\n" }; //$NON-NLS-1$
-
-// private static final int[] EDIT_ACTION_ACCELERATORS = new int[] {
-// createEditActionAccelerator('C'), createEditActionAccelerator('V'), createEditActionAccelerator('A')
-// };
-
- /**
- * This field holds a reference to a TerminalText object that performs all ANSI
- * text processing on data received from the remote host and controls how text is
- * displayed using the view's StyledText widget.
- */
- private final VT100Emulator fTerminalText;
- private Display fDisplay;
- private TextCanvas fCtlText;
- private Composite fWndParent;
- private Clipboard fClipboard;
- private KeyListener fKeyHandler;
- private final ITerminalListener fTerminalListener;
- private String fMsg = ""; //$NON-NLS-1$
- private FocusListener fFocusListener;
- private ITerminalConnector fConnector;
- private final ITerminalConnector[] fConnectors;
- PipedInputStream fInputStream;
- private static final String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
- private String fEncoding = defaultEncoding;
- private InputStreamReader fInputStreamReader;
-
- private ICommandInputField fCommandInputField;
-
- private volatile TerminalState fState;
-
- private final ITerminalTextData fTerminalModel;
-
- /**
- * Is protected by synchronize on this
- */
- volatile private Job fJob;
-
- private final EditActionAccelerators editActionAccelerators = new EditActionAccelerators();
-
- public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
- fConnectors=connectors;
- fTerminalListener=target;
- fTerminalModel=TerminalTextDataFactory.makeTerminalTextData();
- fTerminalModel.setMaxHeight(1000);
- fInputStream=new PipedInputStream(8*1024);
- fTerminalText = new VT100Emulator(fTerminalModel, this, null);
- try {
- // Use Default Encoding as start, until setEncoding() is called
- setEncoding(null);
- } catch (UnsupportedEncodingException e) {
- // Should never happen
- e.printStackTrace();
- // Fall back to local Platform Default Encoding
- fEncoding = defaultEncoding;
- fInputStreamReader = new InputStreamReader(fInputStream);
- fTerminalText.setInputStreamReader(fInputStreamReader);
- }
-
- setupTerminal(wndParent);
- }
-
- @Override public void setEncoding(String encoding) throws UnsupportedEncodingException {
- if (encoding == null) {
- // TODO better use a standard remote-to-local encoding?
- encoding = "ISO-8859-1"; //$NON-NLS-1$
- // TODO or better use the local default encoding?
- // encoding = defaultEncoding;
- }
- fInputStreamReader = new InputStreamReader(fInputStream, encoding);
- // remember encoding if above didn't throw an exception
- fEncoding = encoding;
- fTerminalText.setInputStreamReader(fInputStreamReader);
- }
-
- @Override public String getEncoding() {
- return fEncoding;
- }
-
- @Override public ITerminalConnector[] getConnectors() {
- return fConnectors;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#copy()
- */
- @Override public void copy() {
- copy(DND.CLIPBOARD);
- }
-
- private void copy(int clipboardType) {
- String selection = getSelection();
- if (selection == null || selection.isEmpty()) {
- return;
- }
- Object[] data = new Object[] { selection };
- Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
- fClipboard.setContents(data, types, clipboardType);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#paste()
- */
- @Override public void paste() {
- paste(DND.CLIPBOARD);
-// TODO paste in another thread.... to avoid blocking
-// new Thread() {
-// public void run() {
-// for (int i = 0; i < strText.length(); i++) {
-// sendChar(strText.charAt(i), false);
-// }
-//
-// }
-// }.start();
- }
-
- private void paste(int clipboardType) {
- TextTransfer textTransfer = TextTransfer.getInstance();
- String strText = (String) fClipboard.getContents(textTransfer, clipboardType);
- pasteString(strText);
- }
-
- /**
- * @param strText the text to paste
- */
- @Override public boolean pasteString(String strText) {
- if(!isConnected()) {
- return false;
- }
- if (strText == null) {
- return false;
- }
- if (!fEncoding.equals(defaultEncoding)) {
- sendString(strText);
- } else {
- // TODO I do not understand why pasteString would do this here...
- for (int i = 0; i < strText.length(); i++) {
- sendChar(strText.charAt(i), false);
- }
- }
- return true;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#selectAll()
- */
- @Override public void selectAll() {
- getCtlText().selectAll();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#sendKey(char)
- */
- @Override public void sendKey(char character) {
- Event event;
- KeyEvent keyEvent;
-
- event = new Event();
- event.widget = getCtlText();
- event.character = character;
- event.keyCode = 0;
- event.stateMask = 0;
- event.doit = true;
- keyEvent = new KeyEvent(event);
-
- fKeyHandler.keyPressed(keyEvent);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#clearTerminal()
- */
- @Override public void clearTerminal() {
- // The TerminalText object does all text manipulation.
-
- getTerminalText().clearTerminal();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getClipboard()
- */
- @Override public Clipboard getClipboard() {
- return fClipboard;
- }
-
- /**
- * @return non null selection
- */
- @Override public String getSelection() {
- String txt= fCtlText.getSelectionText();
- if(txt==null)
- {
- txt=""; //$NON-NLS-1$
- }
- return txt;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setFocus()
- */
- @Override public boolean setFocus() {
- return getCtlText().setFocus();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isEmpty()
- */
- @Override public boolean isEmpty() {
- return getCtlText().isEmpty();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isDisposed()
- */
- @Override public boolean isDisposed() {
- return getCtlText().isDisposed();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isConnected()
- */
- @Override public boolean isConnected() {
- return fState==TerminalState.CONNECTED;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disposeTerminal()
- */
- @Override public void disposeTerminal() {
- Logger.log("entered."); //$NON-NLS-1$
- disconnectTerminal();
- fClipboard.dispose();
- getTerminalText().dispose();
- }
-
- @Override public void connectTerminal() {
- Logger.log("entered."); //$NON-NLS-1$
- if(getTerminalConnector()==null) {
- return;
- }
- fTerminalText.resetState();
- if(fConnector.getInitializationErrorMessage()!=null) {
- showErrorMessage(NLS.bind(
- TerminalMessages.CannotConnectTo,
- fConnector.getName(),
- fConnector.getInitializationErrorMessage()));
- // we cannot connect because the connector was not initialized
- return;
- }
- getTerminalConnector().connect(this);
- // clean the error message
- setMsg(""); //$NON-NLS-1$
- waitForConnect();
- }
-
- @Override public ITerminalConnector getTerminalConnector() {
- return fConnector;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disconnectTerminal()
- */
- @Override public void disconnectTerminal() {
- Logger.log("entered."); //$NON-NLS-1$
-
- //Disconnect the remote side first
- if (getState()!=TerminalState.CLOSED) {
- if(getTerminalConnector()!=null) {
- getTerminalConnector().disconnect();
- }
- }
-
- //Ensure that a new Job can be started; then clean up old Job.
- Job job;
- synchronized(this) {
- job = fJob;
- fJob = null;
- }
- if (job!=null) {
- job.cancel();
- // Join job to avoid leaving job running after workbench shutdown (333613).
- // Interrupt to be fast enough; cannot close fInputStream since it is re-used (bug 348700).
- Thread t = job.getThread();
- if(t!=null) {
- t.interrupt();
- }
- try {
- job.join();
- } catch (InterruptedException e) {}
- }
- }
-
- // TODO
- private void waitForConnect() {
- Logger.log("entered."); //$NON-NLS-1$
- // TODO
- // Eliminate this code
- while (getState()==TerminalState.CONNECTING) {
- if (fDisplay.readAndDispatch()) {
- continue;
- }
-
- fDisplay.sleep();
- }
- if(getCtlText().isDisposed()) {
- disconnectTerminal();
- return;
- }
- if (!getMsg().equals("")) //$NON-NLS-1$
- {
- showErrorMessage(getMsg());
-
- disconnectTerminal();
- return;
- }
- getCtlText().setFocus();
- startReaderJob();
-
- }
-
- private synchronized void startReaderJob() {
- if(fJob==null) {
- fJob=new Job("Terminal data reader") { //$NON-NLS-1$
- @Override protected IStatus run(IProgressMonitor monitor) {
- IStatus status=Status.OK_STATUS;
- try {
- while(true) {
- while(fInputStream.available()==0 && !monitor.isCanceled()) {
- try {
- fInputStream.waitForAvailable(500);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- if(monitor.isCanceled()) {
- //Do not disconnect terminal here because another reader job may already be running
- status=Status.CANCEL_STATUS;
- break;
- }
- try {
- // TODO: should block when no text is available!
- fTerminalText.processText();
- } catch (Exception e) {
- disconnectTerminal();
- status=new Status(IStatus.ERROR,TerminalPlugin.PLUGIN_ID,e.getLocalizedMessage(),e);
- break;
- }
- }
- } finally {
- // clean the job: start a new one when the connection gets restarted
- // Bug 208145: make sure we do not clean an other job that's already started (since it would become a Zombie)
- synchronized (VT100TerminalControl.this) {
- if (fJob==this) {
- fJob=null;
- }
- }
- }
- return status;
- }
-
- };
- fJob.setSystem(true);
- fJob.schedule();
- }
- }
-
- private void showErrorMessage(String message) {
- String strTitle = TerminalMessages.TerminalError;
- // [168197] Replace JFace MessagDialog by SWT MessageBox
- //MessageDialog.openError( getShell(), strTitle, message);
- MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
- mb.setText(strTitle);
- mb.setMessage(message);
- mb.open();
- }
-
- protected void sendString(String string) {
- try {
- // Send the string after converting it to an array of bytes using the
- // platform's default character encoding.
- //
- // TODO: Find a way to force this to use the ISO Latin-1 encoding.
- // TODO: handle Encoding Errors in a better way
-
- getOutputStream().write(string.getBytes(fEncoding));
- getOutputStream().flush();
- } catch (SocketException socketException) {
- displayTextInTerminal(socketException.getMessage());
-
- String strMsg = TerminalMessages.SocketError
- + "!\n" + socketException.getMessage(); //$NON-NLS-1$
- showErrorMessage(strMsg);
-
- Logger.logException(socketException);
-
- disconnectTerminal();
- } catch (IOException ioException) {
- showErrorMessage(TerminalMessages.IOError + "!\n" + ioException.getMessage());//$NON-NLS-1$
-
- Logger.logException(ioException);
-
- disconnectTerminal();
- }
- }
-
- @Override public Shell getShell() {
- return getCtlText().getShell();
- }
-
- protected void sendChar(char chKey, boolean altKeyPressed) {
- try {
- int byteToSend = chKey;
- OutputStream os = getOutputStream();
- if (os==null) {
- // Bug 207785: NPE when trying to send char while no longer connected
- Logger.log("NOT sending '" + byteToSend + "' because no longer connected"); //$NON-NLS-1$ //$NON-NLS-2$
- } else {
- if (altKeyPressed) {
- // When the ALT key is pressed at the same time that a character is
- // typed, translate it into an ESCAPE followed by the character. The
- // alternative in this case is to set the high bit of the character
- // being transmitted, but that will cause input such as ALT-f to be
- // seen as the ISO Latin-1 character '�', which can be confusing to
- // European users running Emacs, for whom Alt-f should move forward a
- // word instead of inserting the '�' character.
- //
- // TODO: Make the ESCAPE-vs-highbit behavior user configurable.
-
- Logger.log("sending ESC + '" + byteToSend + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- getOutputStream().write('\u001b');
- getOutputStream().write(byteToSend);
- } else {
- Logger.log("sending '" + byteToSend + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- getOutputStream().write(byteToSend);
- }
- getOutputStream().flush();
- }
- } catch (SocketException socketException) {
- Logger.logException(socketException);
-
- displayTextInTerminal(socketException.getMessage());
-
- String strMsg = TerminalMessages.SocketError
- + "!\n" + socketException.getMessage(); //$NON-NLS-1$
-
- showErrorMessage(strMsg);
- Logger.logException(socketException);
-
- disconnectTerminal();
- } catch (IOException ioException) {
- Logger.logException(ioException);
-
- displayTextInTerminal(ioException.getMessage());
-
- String strMsg = TerminalMessages.IOError + "!\n" + ioException.getMessage(); //$NON-NLS-1$
-
- showErrorMessage(strMsg);
- Logger.logException(ioException);
-
- disconnectTerminal();
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setupTerminal(org.eclipse.swt.widgets.Composite)
- */
- @Override public void setupTerminal(Composite parent) {
- Assert.isNotNull(parent);
- fState=TerminalState.CLOSED;
- setupControls(parent);
- setupListeners();
- setupHelp(fWndParent, TerminalPlugin.HELP_VIEW);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#onFontChanged()
- */
- @Override public void setFont(Font font) {
- getCtlText().setFont(font);
- if(fCommandInputField!=null) {
- fCommandInputField.setFont(font);
- }
-
- // Tell the TerminalControl singleton that the font has changed.
- fCtlText.onFontChange();
- getTerminalText().fontChanged();
- }
- @Override public Font getFont() {
- return getCtlText().getFont();
- }
- @Override public Control getControl() {
- return fCtlText;
- }
- @Override public Control getRootControl() {
- return fWndParent;
- }
- protected void setupControls(Composite parent) {
- // The Terminal view now aims to be an ANSI-conforming terminal emulator, so it
- // can't have a horizontal scroll bar (but a vertical one is ok). Also, do
- // _not_ make the TextViewer read-only, because that prevents it from seeing a
- // TAB character when the user presses TAB (instead, the TAB causes focus to
- // switch to another Workbench control). We prevent local keyboard input from
- // modifying the text in method TerminalVerifyKeyListener.verifyKey().
-
- fWndParent=new Composite(parent,SWT.NONE);
- GridLayout layout=new GridLayout();
- layout.marginWidth=0;
- layout.marginHeight=0;
- layout.verticalSpacing=0;
- fWndParent.setLayout(layout);
-
- ITerminalTextDataSnapshot snapshot=fTerminalModel.makeSnapshot();
- // TODO how to get the initial size correctly!
- snapshot.updateSnapshot(false);
- ITextCanvasModel canvasModel=new PollingTextCanvasModel(snapshot);
- fCtlText=new TextCanvas(fWndParent,canvasModel,SWT.NONE,new TextLineRenderer(fCtlText,canvasModel));
- fCtlText.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseUp(MouseEvent e) {
- IHyperlink hyperlink = hyperlinkAt(e);
- if (hyperlink != null) {
- hyperlink.open();
- }
- }
- });
- fCtlText.addMouseMoveListener(new MouseMoveListener() {
- @Override public void mouseMove(MouseEvent e) {
- IHyperlink hyperlink = hyperlinkAt(e);
- int cursorId = (hyperlink == null) ? SWT.CURSOR_IBEAM : SWT.CURSOR_HAND;
- Cursor newCursor = fCtlText.getDisplay().getSystemCursor(cursorId);
- if (!newCursor.equals(fCtlText.getCursor())) {
- fCtlText.setCursor(newCursor);
- }
- }
- });
-
- fCtlText.setLayoutData(new GridData(GridData.FILL_BOTH));
- fCtlText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- fCtlText.addResizeHandler(new TextCanvas.ResizeListener() {
- @Override public void sizeChanged(int lines, int columns) {
- fTerminalText.setDimensions(lines, columns);
- }
- });
- fCtlText.addMouseListener(new MouseAdapter() {
- @Override public void mouseUp(MouseEvent e) {
- // update selection used by middle mouse button paste
- if (e.button == 1 && getSelection().length() > 0) {
- copy(DND.SELECTION_CLIPBOARD);
- }
- }
- });
-
- fDisplay = getCtlText().getDisplay();
- fClipboard = new Clipboard(fDisplay);
-// fViewer.setDocument(new TerminalDocument());
- setFont(JFaceResources.getTextFont());
- }
-
- private IHyperlink hyperlinkAt(MouseEvent e) {
- Point p = fCtlText.screenPointToCell(e.x, e.y);
- if (p != null) {
- List<IHyperlink> hyperlinks = fTerminalText.hyperlinksAt(p.y);
- for (IHyperlink hyperlink : hyperlinks) {
- IRegion region = hyperlink.getHyperlinkRegion();
- int start = region.getOffset();
- int end = start + region.getLength() - 1;
- if (p.x >= start && p.x <= end) {
- return hyperlink;
- }
- }
- }
- return null;
- }
-
- protected void setupListeners() {
- fKeyHandler = new TerminalKeyHandler();
- fFocusListener = new TerminalFocusListener();
-
- getCtlText().addKeyListener(fKeyHandler);
- getCtlText().addFocusListener(fFocusListener);
-
- }
-
- /**
- * Setup all the help contexts for the controls.
- */
- protected void setupHelp(Composite parent, String id) {
- Control[] children = parent.getChildren();
-
- for (int nIndex = 0; nIndex < children.length; nIndex++) {
- if (children[nIndex] instanceof Composite) {
- setupHelp((Composite) children[nIndex], id);
- }
- }
-
- PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, id);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#displayTextInTerminal(java.lang.String)
- */
- @Override public void displayTextInTerminal(String text) {
- writeToTerminal("\r\n"+text+"\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- private void writeToTerminal(String text) {
- try {
- getRemoteToTerminalOutputStream().write(text.getBytes(fEncoding));
- } catch (UnsupportedEncodingException e) {
- // should never happen!
- e.printStackTrace();
- } catch (IOException e) {
- // should never happen!
- e.printStackTrace();
- }
-
- }
-
- @Override public OutputStream getRemoteToTerminalOutputStream() {
- if(Logger.isLogEnabled()) {
- return new LoggingOutputStream(fInputStream.getOutputStream());
- } else {
- return fInputStream.getOutputStream();
- }
- }
- protected boolean isLogCharEnabled() {
- return TerminalPlugin.isOptionEnabled(Logger.TRACE_DEBUG_LOG_CHAR);
- }
- protected boolean isLogBufferSizeEnabled() {
- return TerminalPlugin
- .isOptionEnabled(Logger.TRACE_DEBUG_LOG_BUFFER_SIZE);
- }
-
-
- @Override public OutputStream getOutputStream() {
- if(getTerminalConnector()!=null) {
- return getTerminalConnector().getTerminalToRemoteStream();
- }
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setMsg(java.lang.String)
- */
- @Override public void setMsg(String msg) {
- fMsg = msg;
- }
-
- public String getMsg() {
- return fMsg;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getCtlText()
- */
- protected TextCanvas getCtlText() {
- return fCtlText;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getTerminalText()
- */
- public VT100Emulator getTerminalText() {
- return fTerminalText;
- }
- protected class TerminalFocusListener implements FocusListener {
- private IContextActivation contextActivation = null;
-
- protected TerminalFocusListener() {
- super();
- }
-
- @Override public void focusGained(FocusEvent event) {
- // Disable all keyboard accelerators (e.g., Control-B) so the Terminal view
- // can see every keystroke. Without this, Emacs, vi, and Bash are unusable
- // in the Terminal view.
-
- IBindingService bindingService = (IBindingService) PlatformUI
- .getWorkbench().getAdapter(IBindingService.class);
- bindingService.setKeyFilterEnabled(false);
-
- // The above code fails to cause Eclipse to disable menu-activation
- // accelerators (e.g., Alt-F for the File menu), so we set the command
- // context to be the Terminal view's command context. This enables us to
- // override menu-activation accelerators with no-op commands in our
- // plugin.xml file, which enables the Terminal view to see absolutly _all_
- // key-presses.
-
- IContextService contextService = (IContextService) PlatformUI
- .getWorkbench().getAdapter(IContextService.class);
- contextActivation = contextService
- .activateContext("org.eclipse.tm.terminal.TerminalContext"); //$NON-NLS-1$
- }
-
- @Override public void focusLost(FocusEvent event) {
- // Enable all keybindings.
-
- IBindingService bindingService = (IBindingService) PlatformUI
- .getWorkbench().getAdapter(IBindingService.class);
- bindingService.setKeyFilterEnabled(true);
-
- // Restore the command context to its previous value.
-
- IContextService contextService = (IContextService) PlatformUI
- .getWorkbench().getAdapter(IContextService.class);
- contextService.deactivateContext(contextActivation);
- }
- }
-
- protected class TerminalKeyHandler extends KeyAdapter {
- @Override public void keyPressed(KeyEvent event) {
- if (getState()==TerminalState.CONNECTING) {
- return;
- }
-
- int accelerator = convertEventToUnmodifiedAccelerator(event);
- if (editActionAccelerators.isCopyAction(accelerator)) {
- copy();
- return;
- }
- if (editActionAccelerators.isPasteAction(accelerator)) {
- paste();
- return;
- }
-
- // We set the event.doit to false to prevent any further processing of this
- // key event. The only reason this is here is because I was seeing the F10
- // key both send an escape sequence (due to this method) and switch focus
- // to the Workbench File menu (forcing the user to click in the Terminal
- // view again to continue entering text). This fixes that.
-
- event.doit = false;
-
- char character = event.character;
-
- //if (!isConnected()) {
- if (fState==TerminalState.CLOSED) {
- // Pressing ENTER while not connected causes us to connect.
- if (character == '\r') {
- connectTerminal();
- return;
- }
-
- // Ignore all other keyboard input when not connected.
- // Allow other key handlers (such as Ctrl+F1) do their work
- event.doit = true;
- return;
- }
-
- // Manage the Del key
- if (event.keyCode == 0x000007f)
- {
- sendString("\u001b[3~"); //$NON-NLS-1$
- return;
- }
-
- // If the event character is NUL ('\u0000'), then a special key was pressed
- // (e.g., PageUp, PageDown, an arrow key, a function key, Shift, Alt,
- // Control, etc.). The one exception is when the user presses Control-@,
- // which sends a NUL character, in which case we must send the NUL to the
- // remote endpoint. This is necessary so that Emacs will work correctly,
- // because Control-@ (i.e., NUL) invokes Emacs' set-mark-command when Emacs
- // is running on a terminal. When the user presses Control-@, the keyCode
- // is 50.
-
- if (character == '\u0000' && event.keyCode != 50) {
- // A special key was pressed. Figure out which one it was and send the
- // appropriate ANSI escape sequence.
- //
- // IMPORTANT: Control will not enter this method for these special keys
- // unless certain <keybinding> tags are present in the plugin.xml file
- // for the Terminal view. Do not delete those tags.
-
- switch (event.keyCode) {
- case 0x1000001: // Up arrow.
- sendString("\u001b[A"); //$NON-NLS-1$
- break;
-
- case 0x1000002: // Down arrow.
- sendString("\u001b[B"); //$NON-NLS-1$
- break;
-
- case 0x1000003: // Left arrow.
- sendString("\u001b[D"); //$NON-NLS-1$
- break;
-
- case 0x1000004: // Right arrow.
- sendString("\u001b[C"); //$NON-NLS-1$
- break;
-
- case 0x1000005: // PgUp key.
- sendString("\u001b[5~"); //$NON-NLS-1$
- break;
-
- case 0x1000006: // PgDn key.
- sendString("\u001b[6~"); //$NON-NLS-1$
- break;
-
- case 0x1000007: // Home key.
- sendString("\u001b[H"); //$NON-NLS-1$
- break;
-
- case 0x1000008: // End key.
- sendString("\u001b[F"); //$NON-NLS-1$
- break;
-
- case 0x1000009: // Insert.
- sendString("\u001b[2~"); //$NON-NLS-1$
- break;
-
- case 0x100000a: // F1 key.
- if ( (event.stateMask & SWT.CTRL)!=0 ) {
- //Allow Ctrl+F1 to act locally as well as on the remote, because it is
- //typically non-intrusive
- event.doit=true;
- }
- sendString("\u001b[M"); //$NON-NLS-1$
- break;
-
- case 0x100000b: // F2 key.
- sendString("\u001b[N"); //$NON-NLS-1$
- break;
-
- case 0x100000c: // F3 key.
- sendString("\u001b[O"); //$NON-NLS-1$
- break;
-
- case 0x100000d: // F4 key.
- sendString("\u001b[P"); //$NON-NLS-1$
- break;
-
- case 0x100000e: // F5 key.
- sendString("\u001b[Q"); //$NON-NLS-1$
- break;
-
- case 0x100000f: // F6 key.
- sendString("\u001b[R"); //$NON-NLS-1$
- break;
-
- case 0x1000010: // F7 key.
- sendString("\u001b[S"); //$NON-NLS-1$
- break;
-
- case 0x1000011: // F8 key.
- sendString("\u001b[T"); //$NON-NLS-1$
- break;
-
- case 0x1000012: // F9 key.
- sendString("\u001b[U"); //$NON-NLS-1$
- break;
-
- case 0x1000013: // F10 key.
- sendString("\u001b[V"); //$NON-NLS-1$
- break;
-
- case 0x1000014: // F11 key.
- sendString("\u001b[W"); //$NON-NLS-1$
- break;
-
- case 0x1000015: // F12 key.
- sendString("\u001b[X"); //$NON-NLS-1$
- break;
-
- default:
- // Ignore other special keys. Control flows through this case when
- // the user presses SHIFT, CONTROL, ALT, and any other key not
- // handled by the above cases.
- break;
- }
-
- // It's ok to return here, because we never locally echo special keys.
-
- return;
- }
-
- // To fix SPR 110341, we consider the Alt key to be pressed only when the
- // Control key is _not_ also pressed. This works around a bug in SWT where,
- // on European keyboards, the AltGr key being pressed appears to us as Control
- // + Alt being pressed simultaneously.
-
- Logger.log("stateMask = " + event.stateMask); //$NON-NLS-1$
-
- boolean altKeyPressed = (((event.stateMask & SWT.ALT) != 0) && ((event.stateMask & SWT.CTRL) == 0));
-
- if (!altKeyPressed && (event.stateMask & SWT.CTRL) != 0
- && character == ' ') {
- // Send a NUL character -- many terminal emulators send NUL when
- // Control-Space is pressed. This is used to set the mark in Emacs.
-
- character = '\u0000';
- }
-
- sendChar(character, altKeyPressed);
-
- // Special case: When we are in a TCP connection and echoing characters
- // locally, send a LF after sending a CR.
- // ISSUE: Is this absolutely required?
-
- if (character == '\r' && getTerminalConnector() != null
- && isConnected()
- && getTerminalConnector().isLocalEcho()) {
- sendChar('\n', false);
- }
-
- // Now decide if we should locally echo the character we just sent. We do
- // _not_ locally echo the character if any of these conditions are true:
- //
- // o This is a serial connection.
- //
- // o This is a TCP connection (i.e., m_telnetConnection is not null) and
- // the remote endpoint is not a TELNET server.
- //
- // o The ALT (or META) key is pressed.
- //
- // o The character is any of the first 32 ISO Latin-1 characters except
- // Control-I or Control-M.
- //
- // o The character is the DELETE character.
-
- if (getTerminalConnector() == null
- || getTerminalConnector().isLocalEcho() == false || altKeyPressed
- || (character >= '\u0001' && character < '\t')
- || (character > '\t' && character < '\r')
- || (character > '\r' && character <= '\u001f')
- || character == '\u007f') {
- // No local echoing.
- return;
- }
-
- // Locally echo the character.
-
- StringBuffer charBuffer = new StringBuffer();
- charBuffer.append(character);
-
- // If the character is a carriage return, we locally echo it as a CR + LF
- // combination.
-
- if (character == '\r') {
- charBuffer.append('\n');
- }
-
- writeToTerminal(charBuffer.toString());
- }
- }
-
- @Override public void setTerminalTitle(String title) {
- fTerminalListener.setTerminalTitle(title);
- }
-
-
- @Override public TerminalState getState() {
- return fState;
- }
-
-
- @Override public void setState(TerminalState state) {
- fState=state;
- fTerminalListener.setState(state);
- // enable the (blinking) cursor if the terminal is connected
- runAsyncInDisplayThread(new Runnable() {
- @Override public void run() {
- if(fCtlText!=null && !fCtlText.isDisposed()) {
- fCtlText.setCursorEnabled(isConnected());
- }
- }});
- }
- /**
- * @param runnable run in display thread
- */
- private void runAsyncInDisplayThread(Runnable runnable) {
- if(Display.findDisplay(Thread.currentThread())!=null) {
- runnable.run();
- } else if(PlatformUI.isWorkbenchRunning())
- {
- PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
- // else should not happen and we ignore it...
- }
- }
-
- @Override public String getSettingsSummary() {
- if(getTerminalConnector()!=null) {
- return getTerminalConnector().getSettingsSummary();
- }
- return ""; //$NON-NLS-1$
- }
-
- @Override public void setConnector(ITerminalConnector connector) {
- fConnector=connector;
-
- }
- @Override public ICommandInputField getCommandInputField() {
- return fCommandInputField;
- }
-
- @Override public void setCommandInputField(ICommandInputField inputField) {
- if(fCommandInputField!=null) {
- fCommandInputField.dispose();
- }
- fCommandInputField=inputField;
- if(fCommandInputField!=null) {
- fCommandInputField.createControl(fWndParent, this);
- }
- if(fWndParent.isVisible()) {
- fWndParent.layout(true);
- }
- }
-
- @Override public int getBufferLineLimit() {
- return fTerminalModel.getMaxHeight();
- }
-
- @Override public void setBufferLineLimit(int bufferLineLimit) {
- if(bufferLineLimit<=0) {
- return;
- }
- synchronized (fTerminalModel) {
- if(fTerminalModel.getHeight()>bufferLineLimit) {
- fTerminalModel.setDimensions(bufferLineLimit, fTerminalModel.getWidth());
- }
- fTerminalModel.setMaxHeight(bufferLineLimit);
- }
- }
-
- @Override public boolean isScrollLock() {
- return fCtlText.isScrollLock();
- }
-
- @Override public void setScrollLock(boolean on) {
- fCtlText.setScrollLock(on);
- }
-
- @Override public void setInvertedColors(boolean invert) {
- fCtlText.setInvertedColors(invert);
- }
-
- public void setColors(RGB background, RGB foreground) {
- fCtlText.setColors(background, foreground);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/ISnapshotChanges.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/ISnapshotChanges.java
deleted file mode 100644
index b81fef7..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/ISnapshotChanges.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-
-public interface ISnapshotChanges {
-
- /**
- * @param line might bigger than the number of lines....
- */
- void markLineChanged(int line);
-
- /**
- * Marks all lines in the range as changed
- * @param line >=0
- * @param n might be out of range
- */
- void markLinesChanged(int line, int n);
-
- /**
- * Marks all lines within the scrolling region
- * changed and resets the scrolling information
- */
- void convertScrollingIntoChanges();
-
- /**
- * @return true if something has changed
- */
- boolean hasChanged();
-
- /**
- * @param startLine
- * @param size
- * @param shift
- */
- void scroll(int startLine, int size, int shift);
-
- /**
- * Mark all lines changed
- * @param height if no window is set this is the number of
- * lines that are marked as changed
- */
- void setAllChanged(int height);
-
- int getFirstChangedLine();
-
- int getLastChangedLine();
-
- int getScrollWindowStartLine();
-
- int getScrollWindowSize();
-
- int getScrollWindowShift();
-
- boolean hasLineChanged(int line);
-
- void markDimensionsChanged();
- boolean hasDimensionsChanged();
- void markCursorChanged();
-
- /**
- * @return true if the terminal data has changed
- */
- boolean hasTerminalChanged();
- /**
- * mark the terminal as changed
- */
- void setTerminalChanged();
-
-
- void copyChangedLines(ITerminalTextData dest, ITerminalTextData source);
-
- /**
- * @param startLine -1 means follow the end of the data
- * @param size number of lines to follow
- */
- void setInterestWindow(int startLine, int size);
- int getInterestWindowStartLine();
- int getInterestWindowSize();
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/SnapshotChanges.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/SnapshotChanges.java
deleted file mode 100644
index 4bebcb6..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/SnapshotChanges.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-
-
-/**
- * Collects the changes of the {@link ITerminalTextData}
- *
- */
-public class SnapshotChanges implements ISnapshotChanges {
- /**
- * The first line changed
- */
- private int fFirstChangedLine;
- /**
- * The last line changed
- */
- private int fLastChangedLine;
- private int fScrollWindowStartLine;
- private int fScrollWindowSize;
- private int fScrollWindowShift;
- /**
- * true, if scrolling should not tracked anymore
- */
- private boolean fScrollDontTrack;
- /**
- * The lines that need to be copied
- * into the snapshot (lines that have
- * not changed don't have to be copied)
- */
- private boolean[] fChangedLines;
-
- private int fInterestWindowSize;
- private int fInterestWindowStartLine;
- private boolean fDimensionsChanged;
- private boolean fTerminalHasChanged;
- private boolean fCursorHasChanged;
-
- public SnapshotChanges(int nLines) {
- setChangedLinesLength(nLines);
- fFirstChangedLine=Integer.MAX_VALUE;
- fLastChangedLine=-1;
- }
- public SnapshotChanges(int windowStart, int windowSize) {
- setChangedLinesLength(windowStart+windowSize);
- fFirstChangedLine=Integer.MAX_VALUE;
- fLastChangedLine=-1;
- fInterestWindowStartLine=windowStart;
- fInterestWindowSize=windowSize;
-
- }
- /**
- * This is used in asserts to throw an {@link RuntimeException}.
- * This is useful for tests.
- * @return never -- throws an exception
- */
- private boolean throwRuntimeException() {
- throw new RuntimeException();
- }
- /**
- * @param line
- * @param size
- * @return true if the range overlaps with the interest window
- */
- boolean isInInterestWindow(int line, int size) {
- if(fInterestWindowSize<=0)
- return true;
- if(line+size<=fInterestWindowStartLine || line>=fInterestWindowStartLine+fInterestWindowSize)
- return false;
- return true;
- }
- /**
- * @param line
- * @return true if the line is within the interest window
- */
- boolean isInInterestWindow(int line) {
- if(fInterestWindowSize<=0)
- return true;
- if(line<fInterestWindowStartLine || line>=fInterestWindowStartLine+fInterestWindowSize)
- return false;
- return true;
- }
- /**
- * @param line
- * @return the line within the window
- */
- int fitLineToWindow(int line) {
- if(fInterestWindowSize<=0)
- return line;
- if(line<fInterestWindowStartLine)
- return fInterestWindowStartLine;
- return line;
- }
- /**
- * The result is only defined if {@link #isInInterestWindow(int, int)} returns true!
- * @param line the line <b>before</b> {@link #fitLineToWindow(int)} has been called!
- * @param size
- * @return the adjusted size.
- * <p>Note:</p> {@link #fitLineToWindow(int)} has to be called on the line to
- * move the window correctly!
- */
- int fitSizeToWindow(int line, int size) {
- if(fInterestWindowSize<=0)
- return size;
- if(line<fInterestWindowStartLine) {
- size-=fInterestWindowStartLine-line;
- line=fInterestWindowStartLine;
- }
- if(line+size>fInterestWindowStartLine+fInterestWindowSize)
- size=fInterestWindowStartLine+fInterestWindowSize-line;
- return size;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#markLineChanged(int)
- */
- public void markLineChanged(int line) {
- if(!isInInterestWindow(line))
- return;
- line=fitLineToWindow(line);
- if(line<fFirstChangedLine)
- fFirstChangedLine=line;
- if(line>fLastChangedLine)
- fLastChangedLine=line;
- // in case the terminal got resized we expand
- // don't remember the changed line because
- // there is nothing to copy
- if(line<getChangedLineLength()) {
- setChangedLine(line,true);
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#markLinesChanged(int, int)
- */
- public void markLinesChanged(int line, int n) {
- if(n<=0 || !isInInterestWindow(line,n))
- return;
- // do not exceed the bounds of fChangedLines
- // the terminal might have been resized and
- // we can only keep changes for the size of the
- // previous terminal
- n=fitSizeToWindow(line, n);
- line=fitLineToWindow(line);
- int m=Math.min(line+n, getChangedLineLength());
- for (int i = line; i < m; i++) {
- setChangedLine(i,true);
- }
- // this sets fFirstChangedLine as well
- markLineChanged(line);
- // this sets fLastChangedLine as well
- markLineChanged(line+n-1);
- }
- public void markCursorChanged() {
- fCursorHasChanged=true;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#convertScrollingIntoChanges()
- */
- public void convertScrollingIntoChanges() {
- markLinesChanged(fScrollWindowStartLine,fScrollWindowSize);
- fScrollWindowStartLine=0;
- fScrollWindowSize=0;
- fScrollWindowShift=0;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#hasChanged()
- */
- public boolean hasChanged() {
- if(fFirstChangedLine!=Integer.MAX_VALUE || fLastChangedLine>0 || fScrollWindowShift!=0 ||fDimensionsChanged || fCursorHasChanged)
- return true;
- return false;
- }
- public void markDimensionsChanged() {
- fDimensionsChanged=true;
- }
- public boolean hasDimensionsChanged() {
- return fDimensionsChanged;
- }
- public boolean hasTerminalChanged() {
- return fTerminalHasChanged;
- }
- public void setTerminalChanged() {
- fTerminalHasChanged=true;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#scroll(int, int, int)
- */
- public void scroll(int startLine, int size, int shift) {
- size=fitSizeToWindow(startLine, size);
- startLine=fitLineToWindow(startLine);
- // let's track only negative shifts
- if(fScrollDontTrack) {
- // we are in a state where we cannot track scrolling
- // so let's simply mark the scrolled lines as changed
- markLinesChanged(startLine, size);
- } else if(shift>=0) {
- // we cannot handle positive scroll
- // forget about clever caching of scroll events
- doNotTrackScrollingAnymore();
- // mark all lines inside the scroll region as changed
- markLinesChanged(startLine, size);
- } else {
- // we have already scrolled
- if(fScrollWindowShift<0) {
- // we have already scrolled
- if(fScrollWindowStartLine==startLine && fScrollWindowSize==size) {
- // we are scrolling the same region again?
- fScrollWindowShift+=shift;
- scrollChangesLinesWithNegativeShift(startLine,size,shift);
- } else {
- // mark all lines in the old scroll region as changed
- doNotTrackScrollingAnymore();
- // mark all lines changed, because
- markLinesChanged(startLine, size);
- }
- } else {
- // first scroll in this change -- we just notify it
- fScrollWindowStartLine=startLine;
- fScrollWindowSize=size;
- fScrollWindowShift=shift;
- scrollChangesLinesWithNegativeShift(startLine,size,shift);
- }
- }
- }
- /**
- * Some incompatible scrolling occurred. We cannot do the
- * scroll optimization anymore...
- */
- private void doNotTrackScrollingAnymore() {
- if(fScrollWindowSize>0) {
- // convert the current scrolling into changes
- markLinesChanged(fScrollWindowStartLine, fScrollWindowSize);
- fScrollWindowStartLine=0;
- fScrollWindowSize=0;
- fScrollWindowShift=0;
- }
- // don't be clever on scrolling anymore
- fScrollDontTrack=true;
- }
- /**
- * Scrolls the changed lines data
- *
- * @param line
- * @param n
- * @param shift must be negative!
- */
- private void scrollChangesLinesWithNegativeShift(int line, int n, int shift) {
- assert shift <0 || throwRuntimeException();
- // scroll the region
- // don't run out of bounds!
- int m=Math.min(line+n+shift,getChangedLineLength()+shift);
- for (int i = line; i < m; i++) {
- setChangedLine(i, hasLineChanged(i-shift));
- // move the first changed line up.
- // We don't have to move the maximum down,
- // because with a shift scroll, the max is moved
- // my the next loop in this method
- if(i<fFirstChangedLine && hasLineChanged(i)) {
- fFirstChangedLine=i;
- }
- }
- // mark the "opened" lines as changed
- for (int i = Math.max(0,line+n+shift); i < line+n; i++) {
- markLineChanged(i);
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#setAllChanged(int)
- */
- public void setAllChanged(int height) {
- fScrollWindowStartLine=0;
- fScrollWindowSize=0;
- fScrollWindowShift=0;
- fFirstChangedLine=fitLineToWindow(0);
- fLastChangedLine=fFirstChangedLine+fitSizeToWindow(0, height)-1;
- // no need to keep an array of changes anymore
- setChangedLinesLength(0);
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#getFirstChangedLine()
- */
- public int getFirstChangedLine() {
- return fFirstChangedLine;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#getLastChangedLine()
- */
- public int getLastChangedLine() {
- return fLastChangedLine;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#getScrollWindowStartLine()
- */
- public int getScrollWindowStartLine() {
- return fScrollWindowStartLine;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#getScrollWindowSize()
- */
- public int getScrollWindowSize() {
- return fScrollWindowSize;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#getScrollWindowShift()
- */
- public int getScrollWindowShift() {
- return fScrollWindowShift;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#copyChangedLines(org.eclipse.tm.terminal.model.ITerminalTextData, org.eclipse.tm.terminal.model.ITerminalTextData)
- */
- public void copyChangedLines(ITerminalTextData dest, ITerminalTextData source) {
- int n=Math.min(fLastChangedLine+1,source.getHeight());
- for (int i = fFirstChangedLine; i < n ; i++) {
- if(hasLineChanged(i))
- dest.copyLine(source,i,i);
- }
- }
-
- public int getInterestWindowSize() {
- return fInterestWindowSize;
- }
-
- public int getInterestWindowStartLine() {
- return fInterestWindowStartLine;
- }
-
- public void setInterestWindow(int startLine, int size) {
- int oldStartLine=fInterestWindowStartLine;
- int oldSize=fInterestWindowSize;
- fInterestWindowStartLine=startLine;
- fInterestWindowSize=size;
- if(oldSize>0) {
- int shift=oldStartLine-startLine;
- if(shift==0) {
- if(size>oldSize) {
- // add lines to the end
- markLinesChanged(oldStartLine+oldSize, size-oldSize);
- }
- // else no lines within the window have changed
-
- } else if(Math.abs(shift)<size) {
- if(shift<0) {
- // we can scroll
- scroll(startLine, oldSize, shift);
- // mark the lines at the end as new
- for (int i = oldStartLine+oldSize; i < startLine+size; i++) {
- markLineChanged(i);
- }
- } else {
- // we cannot shift positive -- mark all changed
- markLinesChanged(startLine, size);
- }
- } else {
- // no scrolling possible
- markLinesChanged(startLine, size);
- }
-
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ISnapshotChanges#hasLineChanged(int)
- */
- public boolean hasLineChanged(int line) {
- if(line<fChangedLines.length)
- return fChangedLines[line];
- // since the height of the terminal could
- // have changed but we have tracked only changes
- // of the previous terminal height, any line outside
- // the the range of the previous height has changed
- return isInInterestWindow(line);
- }
- int getChangedLineLength() {
- return fChangedLines.length;
- }
- void setChangedLine(int line,boolean changed){
- fChangedLines[line]=changed;
- }
- void setChangedLinesLength(int length) {
- fChangedLines=new boolean[length];
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/SynchronizedTerminalTextData.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/SynchronizedTerminalTextData.java
deleted file mode 100644
index 0bbf8d2..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/SynchronizedTerminalTextData.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse synchronized public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- * This is a decorator to make all access to
- * ITerminalTextData synchronized
- *
- */
-public class SynchronizedTerminalTextData implements ITerminalTextData {
- final ITerminalTextData fData;
- public SynchronizedTerminalTextData(ITerminalTextData data) {
- fData=data;
- }
- synchronized public void addLine() {
- fData.addLine();
- }
- synchronized public void cleanLine(int line) {
- fData.cleanLine(line);
- }
- synchronized public void copy(ITerminalTextData source) {
- fData.copy(source);
- }
- synchronized public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
- fData.copyLine(source, sourceLine, destLine);
- }
- synchronized public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine, int length) {
- fData.copyRange(source, sourceStartLine, destStartLine, length);
- }
- synchronized public char getChar(int line, int column) {
- return fData.getChar(line, column);
- }
- synchronized public char[] getChars(int line) {
- return fData.getChars(line);
- }
- synchronized public int getCursorColumn() {
- return fData.getCursorColumn();
- }
- synchronized public int getCursorLine() {
- return fData.getCursorLine();
- }
- synchronized public int getHeight() {
- return fData.getHeight();
- }
- synchronized public LineSegment[] getLineSegments(int line, int startCol, int numberOfCols) {
- return fData.getLineSegments(line, startCol, numberOfCols);
- }
- synchronized public int getMaxHeight() {
- return fData.getMaxHeight();
- }
- synchronized public Style getStyle(int line, int column) {
- return fData.getStyle(line, column);
- }
- synchronized public Style[] getStyles(int line) {
- return fData.getStyles(line);
- }
- synchronized public int getWidth() {
- return fData.getWidth();
- }
- synchronized public ITerminalTextDataSnapshot makeSnapshot() {
- return fData.makeSnapshot();
- }
- synchronized public void scroll(int startLine, int size, int shift) {
- fData.scroll(startLine, size, shift);
- }
- synchronized public void setChar(int line, int column, char c, Style style) {
- fData.setChar(line, column, c, style);
- }
- synchronized public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
- fData.setChars(line, column, chars, start, len, style);
- }
- synchronized public void setChars(int line, int column, char[] chars, Style style) {
- fData.setChars(line, column, chars, style);
- }
- synchronized public void setCursorColumn(int column) {
- fData.setCursorColumn(column);
- }
- synchronized public void setCursorLine(int line) {
- fData.setCursorLine(line);
- }
- synchronized public void setDimensions(int height, int width) {
- fData.setDimensions(height, width);
- }
- synchronized public void setMaxHeight(int height) {
- fData.setMaxHeight(height);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextData.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextData.java
deleted file mode 100644
index 9ec0d1c..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextData.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - [168197] Fix Terminal for CDC-1.1/Foundation-1.1
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- * This class is thread safe.
- *
- */
-public class TerminalTextData implements ITerminalTextData {
- final ITerminalTextData fData;
- /**
- * A list of active snapshots
- */
- public TerminalTextDataSnapshot[] fSnapshots=new TerminalTextDataSnapshot[0];
- private int fCursorColumn;
- private int fCursorLine;
- /**
- * Debug helper method -- use as "New Detail Formatter.." in the
- * debugger variables view:
- * <pre>TerminalTextData.toMultiLineText(this,0,200))</pre>
- * @param term the terminal
- * @param start start line to show
- * @param len number of lines to show -- negative numbers means show all
- * @return a string representation of the content
- */
- static public String toMultiLineText(ITerminalTextDataReadOnly term, int start, int len) {
- if(len<0)
- len=term.getHeight();
- StringBuffer buff=new StringBuffer();
- int width=term.getWidth();
- int n=Math.min(len,term.getHeight()-start);
- for (int line = start; line < n; line++) {
- if(line>0)
- buff.append("\n"); //$NON-NLS-1$
- for (int column = 0; column < width; column++) {
- buff.append(term.getChar(line, column));
- }
- }
- // get rid of the empty space at the end of the lines
- //return buff.toString().replaceAll("\000+", ""); //$NON-NLS-1$//$NON-NLS-2$
- //<J2ME CDC-1.1 Foundation-1.1 variant>
- int i = buff.length() - 1;
- while (i >= 0 && buff.charAt(i) == '\000') {
- i--;
- }
- buff.setLength(i + 1);
- return buff.toString();
- //</J2ME CDC-1.1 Foundation-1.1 variant>
- }
-
- /**
- * Show the first 100 lines
- * see {@link #toMultiLineText(ITerminalTextDataReadOnly, int, int)}
- * @param term A read-only terminal model
- * @return a string representation of the terminal
- */
- static public String toMultiLineText(ITerminalTextDataReadOnly term) {
- return toMultiLineText(term, 0, 100);
- }
-
- public TerminalTextData() {
- this(new TerminalTextDataFastScroll());
-
-// this(new TerminalTextDataStore());
- }
- public TerminalTextData(ITerminalTextData data) {
- fData=data;
- }
- public int getWidth() {
- return fData.getWidth();
- }
- public int getHeight() {
- // no need for an extra variable
- return fData.getHeight();
- }
- public void setDimensions(int height, int width) {
- int h=getHeight();
- int w=getWidth();
- if(w==width && h==height)
- return;
- fData.setDimensions(height, width);
- sendDimensionsChanged(h, w, height, width);
- }
- private void sendDimensionsChanged(int oldHeight, int oldWidth, int newHeight, int newWidth) {
- // determine what has changed
- if(oldWidth==newWidth) {
- if(oldHeight<newHeight)
- sendLinesChangedToSnapshot(oldHeight, newHeight-oldHeight);
- else
- sendLinesChangedToSnapshot(newHeight,oldHeight-newHeight);
- } else {
- sendLinesChangedToSnapshot(0, oldHeight);
- }
- sendDimensionsChanged();
- }
- public LineSegment[] getLineSegments(int line, int column, int len) {
- return fData.getLineSegments(line, column, len);
- }
- public char getChar(int line, int column) {
- return fData.getChar(line, column);
- }
- public Style getStyle(int line, int column) {
- return fData.getStyle(line, column);
- }
- public void setChar(int line, int column, char c, Style style) {
- fData.setChar(line, column, c, style);
- sendLineChangedToSnapshots(line);
- }
- public void setChars(int line, int column, char[] chars, Style style) {
- fData.setChars(line, column, chars, style);
- sendLineChangedToSnapshots(line);
- }
- public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
- fData.setChars(line, column, chars, start, len, style);
- sendLineChangedToSnapshots(line);
- }
- public void scroll(int startLine, int size, int shift) {
- fData.scroll(startLine, size, shift);
- sendScrolledToSnapshots(startLine, size, shift);
- }
- public String toString() {
- return fData.toString();
- }
- private void sendDimensionsChanged() {
- for (int i = 0; i < fSnapshots.length; i++) {
- fSnapshots[i].markDimensionsChanged();
- }
- }
- /**
- * @param line notifies snapshots that line line has changed
- */
- protected void sendLineChangedToSnapshots(int line) {
- for (int i = 0; i < fSnapshots.length; i++) {
- fSnapshots[i].markLineChanged(line);
- }
- }
- /**
- * Notify snapshots that multiple lines have changed
- * @param line changed line
- * @param n number of changed lines
- */
- protected void sendLinesChangedToSnapshot(int line,int n) {
- for (int i = 0; i < fSnapshots.length; i++) {
- fSnapshots[i].markLinesChanged(line, n);
- }
- }
-
- /**
- * Notify snapshot that a region was scrolled
- * @param startLine first line of scrolled region
- * @param size size of scrolled region (number of lines)
- * @param shift delta by which the region is scrolled
- */
- protected void sendScrolledToSnapshots(int startLine,int size, int shift) {
- for (int i = 0; i < fSnapshots.length; i++) {
- fSnapshots[i].scroll(startLine, size, shift);
- }
- }
- protected void sendCursorChanged() {
- for (int i = 0; i < fSnapshots.length; i++) {
- fSnapshots[i].markCursorChanged();
- }
- }
- /**
- * Removes the snapshot from the @observer@ list
- * @param snapshot A snapshot of a terminal model
- */
- protected void removeSnapshot(TerminalTextDataSnapshot snapshot) {
- // poor mans approach to modify the array
- List list=new ArrayList();
- list.addAll(Arrays.asList(fSnapshots));
- list.remove(snapshot);
- fSnapshots=(TerminalTextDataSnapshot[]) list.toArray(new TerminalTextDataSnapshot[list.size()]);
- }
-
- public ITerminalTextDataSnapshot makeSnapshot() {
- // poor mans approach to modify the array
- TerminalTextDataSnapshot snapshot=new TerminalTextDataSnapshot(this);
- snapshot.markDimensionsChanged();
- List list=new ArrayList();
- list.addAll(Arrays.asList(fSnapshots));
- list.add(snapshot);
- fSnapshots=(TerminalTextDataSnapshot[]) list.toArray(new TerminalTextDataSnapshot[list.size()]);
- return snapshot;
- }
- public void addLine() {
- int oldHeight=getHeight();
- fData.addLine();
- // was is an append or a scroll?
- int newHeight=getHeight();
- if(newHeight>oldHeight) {
- //the line was appended
- sendLinesChangedToSnapshot(oldHeight, 1);
- int width=getWidth();
- sendDimensionsChanged(oldHeight, width, newHeight, width);
-
- } else {
- // the line was scrolled
- sendScrolledToSnapshots(0, oldHeight, -1);
- }
-
- }
-
- public void copy(ITerminalTextData source) {
- fData.copy(source);
- fCursorLine=source.getCursorLine();
- fCursorColumn=source.getCursorColumn();
- }
-
- public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
- fData.copyLine(source, sourceLine, destLine);
- }
- public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine, int length) {
- fData.copyRange(source, sourceStartLine, destStartLine, length);
- }
- public char[] getChars(int line) {
- return fData.getChars(line);
- }
- public Style[] getStyles(int line) {
- return fData.getStyles(line);
- }
- public int getMaxHeight() {
- return fData.getMaxHeight();
- }
- public void setMaxHeight(int height) {
- fData.setMaxHeight(height);
- }
- public void cleanLine(int line) {
- fData.cleanLine(line);
- sendLineChangedToSnapshots(line);
- }
- public int getCursorColumn() {
- return fCursorColumn;
- }
- public int getCursorLine() {
- return fCursorLine;
- }
- public void setCursorColumn(int column) {
- fCursorColumn=column;
- sendCursorChanged();
- }
- public void setCursorLine(int line) {
- fCursorLine=line;
- sendCursorChanged();
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataFastScroll.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataFastScroll.java
deleted file mode 100644
index 6038241..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataFastScroll.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- * This class is optimized for scrolling the entire {@link #getHeight()}.
- * The scrolling is done by moving an offset into the data and using
- * the modulo operator.
- *
- */
-public class TerminalTextDataFastScroll implements ITerminalTextData {
-
- final ITerminalTextData fData;
- private int fHeight;
- private int fMaxHeight;
- /**
- * The offset into the array.
- */
- int fOffset;
- public TerminalTextDataFastScroll(ITerminalTextData data,int maxHeight) {
- fMaxHeight=maxHeight;
- fData=data;
- fData.setDimensions(maxHeight, fData.getWidth());
- if(maxHeight>2)
- assert shiftOffset(-2) || throwRuntimeException();
- }
- public TerminalTextDataFastScroll(int maxHeight) {
- this(new TerminalTextDataStore(),maxHeight);
- }
- public TerminalTextDataFastScroll() {
- this(new TerminalTextDataStore(),1);
- }
- /**
- * This is used in asserts to throw an {@link RuntimeException}.
- * This is useful for tests.
- * @return never -- throws an exception
- */
- private boolean throwRuntimeException() {
- throw new RuntimeException();
- }
- /**
- *
- * @param line
- * @return the actual line number in {@link #fData}
- */
- int getPositionOfLine(int line) {
- return (line+fOffset)%fMaxHeight;
- }
- /**
- * Moves offset by delta. This does <b>not</b> move the data!
- * @param delta
- */
- void moveOffset(int delta) {
- assert Math.abs(delta)<fMaxHeight || throwRuntimeException();
- fOffset=(fMaxHeight+fOffset+delta)%fMaxHeight;
-
- }
- /**
- * Test method to shift the offset for testing (if assert ==true)
- * @param shift TODO
- * @return true
- */
- private boolean shiftOffset(int shift) {
- moveOffset(shift);
- return true;
- }
- public void addLine() {
- if(getHeight()<fMaxHeight) {
- setDimensions(getHeight()+1, getWidth());
- } else {
- scroll(0,getHeight(),-1);
- }
- }
- public void cleanLine(int line) {
- fData.cleanLine(getPositionOfLine(line));
- }
-
- public void copy(ITerminalTextData source) {
- int n=source.getHeight();
- setDimensions(source.getHeight(),source.getWidth());
- for (int i = 0; i < n; i++) {
- fData.copyLine(source, i, getPositionOfLine(i));
- }
- }
-
- public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
- fData.copyLine(source, sourceLine, getPositionOfLine(destLine));
- }
-
- public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine, int length) {
- assert (destStartLine>=0 && destStartLine+length<=fHeight) || throwRuntimeException();
- for (int i = 0; i < length; i++) {
- fData.copyLine(source, i+sourceStartLine, getPositionOfLine(i+destStartLine));
- }
- }
-
- public char getChar(int line, int column) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- return fData.getChar(getPositionOfLine(line), column);
- }
-
- public char[] getChars(int line) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- return fData.getChars(getPositionOfLine(line));
- }
-
- public int getHeight() {
- return fHeight;
- }
-
- public LineSegment[] getLineSegments(int line, int startCol, int numberOfCols) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- return fData.getLineSegments(getPositionOfLine(line), startCol, numberOfCols);
- }
-
- public int getMaxHeight() {
- return fMaxHeight;
- }
-
- public Style getStyle(int line, int column) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- return fData.getStyle(getPositionOfLine(line), column);
- }
-
- public Style[] getStyles(int line) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- return fData.getStyles(getPositionOfLine(line));
- }
-
- public int getWidth() {
- return fData.getWidth();
- }
-
- public ITerminalTextDataSnapshot makeSnapshot() {
- return fData.makeSnapshot();
- }
- private void cleanLines(int line, int len) {
- for (int i = line; i < line+len; i++) {
- fData.cleanLine(getPositionOfLine(i));
- }
- }
- public void scroll(int startLine, int size, int shift) {
- assert (startLine>=0 && startLine+size<=fHeight) || throwRuntimeException();
- if(shift>=fMaxHeight || -shift>=fMaxHeight) {
- cleanLines(startLine, fMaxHeight-startLine);
- return;
- }
- if(size==fHeight) {
- // This is the case this class is optimized for!
- moveOffset(-shift);
- // we only have to clean the lines that appear by the move
- if(shift<0) {
- cleanLines(Math.max(startLine, startLine+size+shift),Math.min(-shift, getHeight()-startLine));
- } else {
- cleanLines(startLine, Math.min(shift, getHeight()-startLine));
- }
- } else {
- // we have to copy the lines.
- if(shift<0) {
- // move the region up
- // shift is negative!!
- for (int i = startLine; i < startLine+size+shift; i++) {
- fData.copyLine(fData, getPositionOfLine(i-shift), getPositionOfLine(i));
- }
- // then clean the opened lines
- cleanLines(Math.max(0, startLine+size+shift),Math.min(-shift, getHeight()-startLine));
- } else {
- for (int i = startLine+size-1; i >=startLine && i-shift>=0; i--) {
- fData.copyLine(fData, getPositionOfLine(i-shift), getPositionOfLine(i));
- }
- cleanLines(startLine, Math.min(shift, getHeight()-startLine));
- }
- }
- }
-
- public void setChar(int line, int column, char c, Style style) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- fData.setChar(getPositionOfLine(line), column, c, style);
- }
-
- public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- fData.setChars(getPositionOfLine(line), column, chars, start, len, style);
- }
-
- public void setChars(int line, int column, char[] chars, Style style) {
- assert (line>=0 && line<fHeight) || throwRuntimeException();
- fData.setChars(getPositionOfLine(line), column, chars, style);
- }
-
- public void setDimensions(int height, int width) {
- assert height>=0 || throwRuntimeException();
- assert width>=0 || throwRuntimeException();
- if(height > fMaxHeight)
- setMaxHeight(height);
- fHeight=height;
- if(width!=fData.getWidth())
- fData.setDimensions(fMaxHeight, width);
- }
-
- public void setMaxHeight(int maxHeight) {
- assert maxHeight>=fHeight || throwRuntimeException();
- // move everything to offset0
- int start=getPositionOfLine(0);
- if(start!=0) {
- // invent a more efficient algorithm....
- ITerminalTextData buffer=new TerminalTextDataStore();
- // create a buffer with the expected height
- buffer.setDimensions(maxHeight, getWidth());
- int n=Math.min(fMaxHeight-start,maxHeight);
- // copy the first part
- buffer.copyRange(fData, start, 0, n);
- // copy the second part
- if(n<maxHeight)
- buffer.copyRange(fData, 0, n, Math.min(fMaxHeight-n,maxHeight-n));
- // copy the buffer back to our data
- fData.copy(buffer);
- shiftOffset(-start);
- } else {
- fData.setDimensions(maxHeight, fData.getWidth());
- }
- fMaxHeight=maxHeight;
- }
- public int getCursorColumn() {
- throw new UnsupportedOperationException();
- }
- public int getCursorLine() {
- throw new UnsupportedOperationException();
- }
- public void setCursorColumn(int column) {
- throw new UnsupportedOperationException();
- }
- public void setCursorLine(int line) {
- throw new UnsupportedOperationException();
- }
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataSnapshot.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataSnapshot.java
deleted file mode 100644
index b24c48b..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataSnapshot.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- * The public methods of this class have to be called from one thread!
- *
- * Threading considerations:
- * This class is <b>not threadsafe</b>!
- */
-class TerminalTextDataSnapshot implements ITerminalTextDataSnapshot {
- /**
- * The changes of the current snapshot relative to the
- * previous snapshot
- */
- volatile ISnapshotChanges fCurrentChanges;
- /**
- * Keeps track of changes that happened since the current
- * snapshot has been made.
- */
- ISnapshotChanges fFutureChanges;
- /**
- * Is used as lock and is the reference to the terminal we take snapshots from.
- */
- final TerminalTextData fTerminal;
- /**
- * A snapshot copy of of fTerminal
- */
- // snapshot does not need internal synchronisation
- final TerminalTextDataWindow fSnapshot;
- // this variable is synchronized on fTerminal!
- private SnapshotOutOfDateListener[] fListener=new SnapshotOutOfDateListener[0];
- // this variable is synchronized on fTerminal!
- private boolean fListenersNeedNotify;
- private int fInterestWindowSize;
- private int fInterestWindowStartLine;
-
- TerminalTextDataSnapshot(TerminalTextData terminal) {
- fSnapshot = new TerminalTextDataWindow();
- fTerminal = terminal;
- fCurrentChanges = new SnapshotChanges(fTerminal.getHeight());
- fCurrentChanges.setTerminalChanged();
- fFutureChanges = new SnapshotChanges(fTerminal.getHeight());
- fFutureChanges.markLinesChanged(0, fTerminal.getHeight());
- fListenersNeedNotify=true;
- fInterestWindowSize=-1;
- }
- /**
- * This is used in asserts to throw an {@link RuntimeException}.
- * This is useful for tests.
- * @return never -- throws an exception
- */
- private boolean throwRuntimeException() {
- throw new RuntimeException();
- }
-
- public void detach() {
- fTerminal.removeSnapshot(this);
- }
-
- public boolean isOutOfDate() {
- // this is called from fTerminal, therefore we lock on fTerminal
- synchronized (fTerminal) {
- return fFutureChanges.hasChanged();
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ITerminalTextDataSnapshot#snapshot()
- */
- public void updateSnapshot(boolean detectScrolling) {
- // make sure terminal does not change while we make the snapshot
- synchronized (fTerminal) {
- // let's make the future changes current
- fCurrentChanges=fFutureChanges;
- fFutureChanges=new SnapshotChanges(fTerminal.getHeight());
- fFutureChanges.setInterestWindow(fInterestWindowStartLine, fInterestWindowSize);
- // and update the snapshot
- if(fSnapshot.getHeight()!=fTerminal.getHeight()||fSnapshot.getWidth()!=fTerminal.getWidth()) {
- if(fInterestWindowSize==-1)
- fSnapshot.setWindow(0, fTerminal.getHeight());
- // if the dimensions have changed, we need a full copy
- fSnapshot.copy(fTerminal);
- // and we mark all lines as changed
- fCurrentChanges.setAllChanged(fTerminal.getHeight());
- } else {
- // first we do the scroll on the copy
- int start=fCurrentChanges.getScrollWindowStartLine();
- int lines=Math.min(fCurrentChanges.getScrollWindowSize(), fSnapshot.getHeight()-start);
- fSnapshot.scroll(start, lines, fCurrentChanges.getScrollWindowShift());
- // and then create the snapshot of the changed lines
- fCurrentChanges.copyChangedLines(fSnapshot, fTerminal);
- }
- fListenersNeedNotify=true;
- fSnapshot.setCursorLine(fTerminal.getCursorLine());
- fSnapshot.setCursorColumn(fTerminal.getCursorColumn());
- }
- if(!detectScrolling) {
- // let's pretend there was no scrolling and
- // convert the scrolling into line changes
- fCurrentChanges.convertScrollingIntoChanges();
- }
- }
-
- public char getChar(int line, int column) {
- return fSnapshot.getChar(line, column);
- }
-
- public int getHeight() {
- return fSnapshot.getHeight();
- }
-
- public LineSegment[] getLineSegments(int line, int column, int len) {
- return fSnapshot.getLineSegments(line, column, len);
- }
-
- public Style getStyle(int line, int column) {
- return fSnapshot.getStyle(line, column);
- }
-
- public int getWidth() {
- return fSnapshot.getWidth();
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ITerminalTextDataSnapshot#getFirstChangedLine()
- */
- public int getFirstChangedLine() {
- return fCurrentChanges.getFirstChangedLine();
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ITerminalTextDataSnapshot#getLastChangedLine()
- */
- public int getLastChangedLine() {
- return fCurrentChanges.getLastChangedLine();
- }
-
- public boolean hasLineChanged(int line) {
- return fCurrentChanges.hasLineChanged(line);
- }
- public boolean hasDimensionsChanged() {
- return fCurrentChanges.hasDimensionsChanged();
- }
- public boolean hasTerminalChanged() {
- return fCurrentChanges.hasTerminalChanged();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ITerminalTextDataSnapshot#getScrollChangeY()
- */
- public int getScrollWindowStartLine() {
- return fCurrentChanges.getScrollWindowStartLine();
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ITerminalTextDataSnapshot#getScrollChangeN()
- */
- public int getScrollWindowSize() {
- return fCurrentChanges.getScrollWindowSize();
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.model.ITerminalTextDataSnapshot#getScrollChangeShift()
- */
- public int getScrollWindowShift() {
- return fCurrentChanges.getScrollWindowShift();
- }
-
- /**
- * Announces a change in line line
- * @param line
- */
- void markLineChanged(int line) {
- // threading
- fFutureChanges.markLineChanged(line);
- fFutureChanges.setTerminalChanged();
- notifyListers();
- }
- /**
- * Announces a change of n lines beginning with line line
- * @param line
- * @param n
- */
- void markLinesChanged(int line,int n) {
- fFutureChanges.markLinesChanged(line,n);
- fFutureChanges.setTerminalChanged();
- notifyListers();
- }
-
- void markDimensionsChanged() {
- fFutureChanges.markDimensionsChanged();
- fFutureChanges.setTerminalChanged();
- notifyListers();
- }
- void markCursorChanged() {
- fFutureChanges.markCursorChanged();
- fFutureChanges.setTerminalChanged();
- notifyListers();
- }
-
- /**
- * @param startLine
- * @param size
- * @param shift
- */
- void scroll(int startLine, int size, int shift) {
- fFutureChanges.scroll(startLine,size,shift);
- fFutureChanges.setTerminalChanged();
- notifyListers();
- }
- /**
- * Notifies listeners about the change
- */
- private void notifyListers() {
- // this code has to be called from a block synchronized on fTerminal
- synchronized (fTerminal) {
- if(fListenersNeedNotify) {
- for (int i = 0; i < fListener.length; i++) {
- fListener[i].snapshotOutOfDate(this);
- }
- fListenersNeedNotify=false;
- }
- }
- }
- public ITerminalTextDataSnapshot makeSnapshot() {
- return fSnapshot.makeSnapshot();
- }
-
- synchronized public void addListener(SnapshotOutOfDateListener listener) {
- List list=new ArrayList();
- list.addAll(Arrays.asList(fListener));
- list.add(listener);
- fListener=(SnapshotOutOfDateListener[]) list.toArray(new SnapshotOutOfDateListener[list.size()]);
- }
-
- synchronized public void removeListener(SnapshotOutOfDateListener listener) {
- List list=new ArrayList();
- list.addAll(Arrays.asList(fListener));
- list.remove(listener);
- fListener=(SnapshotOutOfDateListener[]) list.toArray(new SnapshotOutOfDateListener[list.size()]);
- }
- public String toString() {
- return fSnapshot.toString();
- }
-
-
- public int getInterestWindowSize() {
- return fInterestWindowSize;
- }
-
-
- public int getInterestWindowStartLine() {
- return fInterestWindowStartLine;
- }
-
- public void setInterestWindow(int startLine, int size) {
- assert startLine>=0 || throwRuntimeException();
- assert size>=0 || throwRuntimeException();
- fInterestWindowStartLine=startLine;
- fInterestWindowSize=size;
- fSnapshot.setWindow(startLine, size);
- fFutureChanges.setInterestWindow(startLine, size);
- notifyListers();
- }
-
-
- public char[] getChars(int line) {
- return fSnapshot.getChars(line);
- }
-
-
- public Style[] getStyles(int line) {
- return fSnapshot.getStyles(line);
- }
- public int getCursorColumn() {
- return fSnapshot.getCursorColumn();
- }
- public int getCursorLine() {
- return fSnapshot.getCursorLine();
- }
- public ITerminalTextData getTerminalTextData() {
- return fTerminal;
- }
-}
-
-
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataStore.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataStore.java
deleted file mode 100644
index fd85cc3..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataStore.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- * This class is thread safe.
- *
- */
-public class TerminalTextDataStore implements ITerminalTextData {
- private char[][] fChars;
- private Style[][] fStyle;
- private int fWidth;
- private int fHeight;
- private int fMaxHeight;
- private int fCursorColumn;
- private int fCursorLine;
- public TerminalTextDataStore() {
- fChars=new char[0][];
- fStyle=new Style[0][];
- fWidth=0;
- }
- /**
- * This is used in asserts to throw an {@link RuntimeException}.
- * This is useful for tests.
- * @return never -- throws an exception
- */
- private boolean throwRuntimeException() {
- throw new RuntimeException();
- }
-
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#getWidth()
- */
- public int getWidth() {
- return fWidth;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#getHeight()
- */
- public int getHeight() {
- return fHeight;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#setDimensions(int, int)
- */
- public void setDimensions(int height, int width) {
- assert height>=0 || throwRuntimeException();
- assert width>=0 || throwRuntimeException();
- // just extend the region
- if(height>fChars.length) {
- int h=4*height/3;
- if(fMaxHeight>0 && h>fMaxHeight)
- h=fMaxHeight;
- fStyle=(Style[][]) resizeArray(fStyle, height);
- fChars=(char[][]) resizeArray(fChars, height);
- }
- // clean the new lines
- if(height>fHeight) {
- for (int i = fHeight; i < height; i++) {
- fStyle[i]=null;
- fChars[i]=null;
- }
- }
- // set dimensions after successful resize!
- fWidth=width;
- fHeight=height;
- }
- /**
- * Reallocates an array with a new size, and copies the contents of the old
- * array to the new array.
- *
- * @param origArray the old array, to be reallocated.
- * @param newSize the new array size.
- * @return A new array with the same contents (chopped off if needed or filled with 0 or null).
- */
- private Object resizeArray(Object origArray, int newSize) {
- int oldSize = Array.getLength(origArray);
- if(oldSize==newSize)
- return origArray;
- Class elementType = origArray.getClass().getComponentType();
- Object newArray = Array.newInstance(elementType, newSize);
- int preserveLength = Math.min(oldSize, newSize);
- if (preserveLength > 0)
- System.arraycopy(origArray, 0, newArray, 0, preserveLength);
- return newArray;
- }
-
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#getLineSegments(int, int, int)
- */
- public LineSegment[] getLineSegments(int line, int column, int len) {
- // get the styles and chars for this line
- Style[] styles=fStyle[line];
- char[] chars=fChars[line];
- int col=column;
- int n=column+len;
-
- // expand the line if needed....
- if(styles==null)
- styles=new Style[n];
- else if(styles.length<n)
- styles=(Style[]) resizeArray(styles, n);
-
- if(chars==null)
- chars=new char[n];
- else if(chars.length<n)
- chars=(char[]) resizeArray(chars, n);
-
- // and create the line segments
- Style style=styles[column];
- List segments=new ArrayList();
- for (int i = column; i < n; i++) {
- if(styles[i]!=style) {
- segments.add(new LineSegment(col,new String(chars,col,i-col),style));
- style=styles[i];
- col=i;
- }
- }
- if(col < n) {
- segments.add(new LineSegment(col,new String(chars,col,n-col),style));
- }
- return (LineSegment[]) segments.toArray(new LineSegment[segments.size()]);
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#getChar(int, int)
- */
- public char getChar(int line, int column) {
- assert column<fWidth || throwRuntimeException();
- if(fChars[line]==null||column>=fChars[line].length)
- return 0;
- return fChars[line][column];
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#getStyle(int, int)
- */
- public Style getStyle(int line, int column) {
- assert column<fWidth || throwRuntimeException();
- if(fStyle[line]==null || column>=fStyle[line].length)
- return null;
- return fStyle[line][column];
- }
-
- void ensureLineLength(int iLine, int length) {
- if(length>fWidth)
- throw new RuntimeException();
- if(fChars[iLine]==null) {
- fChars[iLine]=new char[length];
- } else if(fChars[iLine].length<length) {
- fChars[iLine]=(char[]) resizeArray(fChars[iLine],length);
- }
- if(fStyle[iLine]==null) {
- fStyle[iLine]=new Style[length];
- } else if(fStyle[iLine].length<length) {
- fStyle[iLine]=(Style[]) resizeArray(fStyle[iLine],length);
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#setChar(int, int, char, org.eclipse.tm.internal.terminal.text.Style)
- */
- public void setChar(int line, int column, char c, Style style) {
- ensureLineLength(line,column+1);
- fChars[line][column]=c;
- fStyle[line][column]=style;
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#setChars(int, int, char[], org.eclipse.tm.internal.terminal.text.Style)
- */
- public void setChars(int line, int column, char[] chars, Style style) {
- setChars(line,column,chars,0,chars.length,style);
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#setChars(int, int, char[], int, int, org.eclipse.tm.internal.terminal.text.Style)
- */
- public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
- ensureLineLength(line,column+len);
- for (int i = 0; i < len; i++) {
- fChars[line][column+i]=chars[i+start];
- fStyle[line][column+i]=style;
- }
- }
- /* (non-Javadoc)
- * @see org.eclipse.tm.internal.terminal.text.ITerminalTextData#scroll(int, int, int)
- */
- public void scroll(int startLine, int size, int shift) {
- assert startLine+size <= getHeight() || throwRuntimeException();
- if(shift<0) {
- // move the region up
- // shift is negative!!
- for (int i = startLine; i < startLine+size+shift; i++) {
- fChars[i]=fChars[i-shift];
- fStyle[i]=fStyle[i-shift];
- }
- // then clean the opened lines
- cleanLines(Math.max(startLine, startLine+size+shift),Math.min(-shift, getHeight()-startLine));
-// cleanLines(Math.max(0, startLine+size+shift),Math.min(-shift, getHeight()-startLine));
- } else {
- for (int i = startLine+size-1; i >=startLine && i-shift>=0; i--) {
- fChars[i]=fChars[i-shift];
- fStyle[i]=fStyle[i-shift];
- }
- cleanLines(startLine, Math.min(shift, getHeight()-startLine));
- }
- }
- /**
- * Replaces the lines with new empty data
- * @param line
- * @param len
- */
- private void cleanLines(int line, int len) {
- for (int i = line; i < line+len; i++) {
- fChars[i]=null;
- fStyle[i]=null;
- }
- }
-
- /*
- * @return a text representation of the object.
- * Lines are separated by '\n'. No style information is returned.
- */
- public String toString() {
- StringBuffer buff=new StringBuffer();
- for (int line = 0; line < getHeight(); line++) {
- if(line>0)
- buff.append("\n"); //$NON-NLS-1$
- for (int column = 0; column < fWidth; column++) {
- buff.append(getChar(line, column));
- }
- }
- return buff.toString();
- }
-
-
- public ITerminalTextDataSnapshot makeSnapshot() {
- throw new UnsupportedOperationException();
- }
-
- public void addLine() {
- if(fMaxHeight>0 && getHeight()<fMaxHeight) {
- setDimensions(getHeight()+1, getWidth());
- } else {
- scroll(0,getHeight(),-1);
- }
- }
-
- public void copy(ITerminalTextData source) {
- fWidth=source.getWidth();
- int n=source.getHeight();
- if(getHeight()!=n) {
- fChars=new char[n][];
- fStyle=new Style[n][];
- }
- for (int i = 0; i < n; i++) {
- fChars[i]=source.getChars(i);
- fStyle[i]=source.getStyles(i);
- }
- fHeight=n;
- fCursorLine=source.getCursorLine();
- fCursorColumn=source.getCursorColumn();
- }
- public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine,int length) {
- for (int i = 0; i < length; i++) {
- fChars[i+destStartLine]=source.getChars(i+sourceStartLine);
- fStyle[i+destStartLine]=source.getStyles(i+sourceStartLine);
- }
- }
-
- public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
- fChars[destLine]=source.getChars(sourceLine);
- fStyle[destLine]=source.getStyles(sourceLine);
- }
-
- public char[] getChars(int line) {
- if(fChars[line]==null)
- return null;
- return (char[]) fChars[line].clone();
- }
-
- public Style[] getStyles(int line) {
- if(fStyle[line]==null)
- return null;
- return (Style[]) fStyle[line].clone();
- }
-
- public void setLine(int line, char[] chars, Style[] styles) {
- fChars[line]=(char[]) chars.clone();
- fStyle[line]=(Style[]) styles.clone();
- }
-
- public void setMaxHeight(int height) {
- fMaxHeight=height;
- }
-
- public int getMaxHeight() {
- return fMaxHeight;
- }
-
- public void cleanLine(int line) {
- fChars[line]=null;
- fStyle[line]=null;
- }
- public int getCursorColumn() {
- return fCursorColumn;
- }
- public int getCursorLine() {
- return fCursorLine;
- }
- public void setCursorColumn(int column) {
- fCursorColumn=column;
- }
- public void setCursorLine(int line) {
- fCursorLine=line;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataWindow.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataWindow.java
deleted file mode 100644
index 0c4072c..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/model/TerminalTextDataWindow.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.model;
-
-import org.eclipse.tm.terminal.model.ITerminalTextData;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- * This class stores the data only within a window {@link #setWindow(int, int)} and
- * {@link #getWindowStartLine()} and {@link #getWindowSize()}. Everything outside
- * the is <code>char=='\000'</code> and <code>style=null</code>.
- *
- */
-public class TerminalTextDataWindow implements ITerminalTextData {
- final ITerminalTextData fData;
- int fWindowStartLine;
- int fWindowSize;
- int fHeight;
- int fMaxHeight;
- public TerminalTextDataWindow(ITerminalTextData data) {
- fData=data;
- }
- public TerminalTextDataWindow() {
- this(new TerminalTextDataStore());
- }
- /**
- * This is used in asserts to throw an {@link RuntimeException}.
- * This is useful for tests.
- * @return never -- throws an exception
- */
- private boolean throwRuntimeException() {
- throw new RuntimeException();
- }
- /**
- * @param line
- * @return true if the line is within the window
- */
- boolean isInWindow(int line) {
- return line>=fWindowStartLine && line<fWindowStartLine+fWindowSize;
- }
- public char getChar(int line, int column) {
- if(!isInWindow(line))
- return 0;
- return fData.getChar(line-fWindowStartLine, column);
- }
-
- public char[] getChars(int line) {
- if(!isInWindow(line))
- return null;
- return fData.getChars(line-fWindowStartLine);
- }
-
- public int getHeight() {
- return fHeight;
- }
-
- public LineSegment[] getLineSegments(int line, int startCol, int numberOfCols) {
- if(!isInWindow(line))
- return new LineSegment[]{new LineSegment(startCol,new String(new char[numberOfCols]),null)};
- return fData.getLineSegments(line-fWindowStartLine, startCol, numberOfCols);
- }
-
- public int getMaxHeight() {
- return fMaxHeight;
- }
-
- public Style getStyle(int line, int column) {
- if(!isInWindow(line))
- return null;
- return fData.getStyle(line-fWindowStartLine, column);
- }
-
- public Style[] getStyles(int line) {
- if(!isInWindow(line))
- return null;
- return fData.getStyles(line-fWindowStartLine);
- }
-
- public int getWidth() {
- return fData.getWidth();
- }
-
- public ITerminalTextDataSnapshot makeSnapshot() {
- throw new UnsupportedOperationException();
- }
- public void addLine() {
- if(fMaxHeight>0 && getHeight()<fMaxHeight) {
- setDimensions(getHeight()+1, getWidth());
- } else {
- scroll(0,getHeight(),-1);
- }
- }
- public void copy(ITerminalTextData source) {
- // we inherit the dimensions of the source
- setDimensions(source.getHeight(), source.getWidth());
- int n=Math.min(fWindowSize, source.getHeight()-fWindowStartLine);
- if(n>0)
- fData.copyRange(source, fWindowStartLine, 0, n);
- }
- public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine, int length) {
- int n=length;
- int dStart=destStartLine-fWindowStartLine;
- int sStart=sourceStartLine;
- // if start outside our range, cut the length to copy
- if(dStart<0) {
- n+=dStart;
- sStart-=dStart;
- dStart=0;
- }
- // do not exceed the window size
- n=Math.min(n,fWindowSize);
- if(n>0)
- fData.copyRange(source, sStart, dStart, n);
-
- }
- public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
- if(isInWindow(destLine))
- fData.copyLine(source, sourceLine, destLine-fWindowStartLine);
- }
- public void scroll(int startLine, int size, int shift) {
- assert (startLine>=0 && startLine+size<=fHeight) || throwRuntimeException();
- int n=size;
- int start=startLine-fWindowStartLine;
- // if start outside our range, cut the length to copy
- if(start<0) {
- n+=start;
- start=0;
- }
- n=Math.min(n,fWindowSize-start);
- // do not exceed the window size
- if(n>0)
- fData.scroll(start, n, shift);
- }
- public void setChar(int line, int column, char c, Style style) {
- if(!isInWindow(line))
- return;
- fData.setChar(line-fWindowStartLine, column, c, style);
- }
- public void setChars(int line, int column, char[] chars, int start, int len, Style style) {
- if(!isInWindow(line))
- return;
- fData.setChars(line-fWindowStartLine, column, chars, start, len, style);
- }
- public void setChars(int line, int column, char[] chars, Style style) {
- if(!isInWindow(line))
- return;
- fData.setChars(line-fWindowStartLine, column, chars, style);
- }
- public void setDimensions(int height, int width) {
- assert height>=0 || throwRuntimeException();
- fData.setDimensions(fWindowSize, width);
- fHeight=height;
- }
- public void setMaxHeight(int height) {
- fMaxHeight=height;
- }
- public void setWindow(int startLine, int size) {
-// assert startLine+size<=getHeight()||throwRuntimeException();
- fWindowStartLine=startLine;
- fWindowSize=size;
- fData.setDimensions(fWindowSize, getWidth());
- }
- public int getWindowStartLine() {
- return fWindowStartLine;
- }
- public int getWindowSize() {
- return fWindowSize;
- }
- public void setHeight(int height) {
- fHeight = height;
- }
- public void cleanLine(int line) {
- if(isInWindow(line))
- fData.cleanLine(line-fWindowStartLine);
- }
- public int getCursorColumn() {
- return fData.getCursorColumn();
- }
- public int getCursorLine() {
- return fData.getCursorLine();
- }
- public void setCursorColumn(int column) {
- fData.setCursorColumn(column);
- }
- public void setCursorLine(int line) {
- fData.setCursorLine(line);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ISettingsPage.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ISettingsPage.java
deleted file mode 100644
index b75c0c8..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ISettingsPage.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-import org.eclipse.swt.widgets.Composite;
-
-/**
- * @author Michael Scharf
- *
- * TODO: Michael Scharf: provide a mechanism to set an error string
- * TODO: Michael Scharf: provide a long description of a wizard
- * TODO: Michael Scharf: allow multiple pages to be generated
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
- * part of a work in progress. There is no guarantee that this API will
- * work or that it will remain the same. Please do not use this API without
- * consulting with the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public interface ISettingsPage {
- /**
- * Create a page to be shown in a dialog or wizard to setup the connection.
- * @param parent
- */
- void createControl(Composite parent);
-
- /**
- * Called before the page is shown. Loads the state from the {@link ITerminalConnector}.
- */
- void loadSettings();
-
- /**
- * Called when the OK button is pressed.
- */
- void saveSettings();
-
- /**
- * @return true if the
- */
- boolean validateSettings();
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ISettingsStore.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ISettingsStore.java
deleted file mode 100644
index 8822af3..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ISettingsStore.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-/**
- * A simple interface to a store to persist the state of a connection.
- *
- * @author Michael Scharf
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
- * part of a work in progress. There is no guarantee that this API will
- * work or that it will remain the same. Please do not use this API without
- * consulting with the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public interface ISettingsStore {
- /**
- * @param key alpha numeric key, may contain dots (.)
- * @return value
- */
- String get(String key);
-
- /**
- * @param key alpha numeric key, may contain dots (.)
- * @param defaultValue
- * @return the value or the default
- */
- String get(String key, String defaultValue);
-
- /**
- * Save a string value
- * @param key alpha numeric key, may contain dots (.)
- * @param value
- */
- void put(String key, String value);
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java
deleted file mode 100644
index 43a4de2..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
- * Uwe Stieber (Wind River) - [282996] [terminal][api] Add "hidden" attribute to terminal connector extension point
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-import java.io.OutputStream;
-
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
-
-/**
- * A contributed connection type to manage a single connection.
- *
- * Implementations of this class are contributed through the
- * <code>org.eclipse.tm.terminal.terminalConnectors</code> extension point. This
- * class gives access to the static markup of a terminal connector extension as
- * well as providing the lifecycle management for the dynamically loaded
- * {@link TerminalConnectorImpl} instance, which performs the actual
- * communications. This pattern allows for lazy initialization, bundle
- * activation and class loading of the actual {@link TerminalConnectorImpl}
- * instance.
- *
- * Clients can get terminal connector instances from the
- * {@link TerminalConnectorExtension} class, or from
- * {@link ITerminalViewControl#getTerminalConnector()} when running inside an
- * active terminal widget.
- *
- * @noimplement This interface is not intended to be implemented by clients.
- * @noextend This interface is not intended to be extended by clients.
- *
- * @author Michael Scharf
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added
- * as part of a work in progress. There is no guarantee that this API
- * will work or that it will remain the same. Please do not use this API
- * without consulting with the <a
- * href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public interface ITerminalConnector extends IAdaptable {
- /**
- * @return an ID of this connector. The id from the plugin.xml.
- * @since org.eclipse.tm.terminal 2.0
- */
- String getId();
-
- /**
- * @return <code>null</code> the name (as specified in the plugin.xml)
- * @since org.eclipse.tm.terminal 2.0
- */
- String getName();
-
- /**
- * @return <code>True</code> if the connector is not visible in user
- * selections.
- * @since org.eclipse.tm.terminal 3.0.1
- */
- boolean isHidden();
-
- /**
- * @return true if the {@link TerminalConnectorImpl} has been initialized.
- * If there was an initialization error, {@link #getInitializationErrorMessage()}
- * returns the error message.
- * @since org.eclipse.tm.terminal 2.0
- */
- boolean isInitialized();
-
- /**
- * This method initializes the connector if it is not initialized!
- * If the connector was initialized successfully, <code>null</code> is
- * returned. Otherwise an error message describing the problem is returned.
- * @return <code>null</code> or a localized error message.
- * @since org.eclipse.tm.terminal 2.0
- */
- String getInitializationErrorMessage();
-
- /**
- * Connect using the current state of the settings.
- * @param control Used to inform the UI about state changes and messages from the connection.
- */
- void connect(ITerminalControl control);
-
- /**
- * Disconnect if connected. Else do nothing.
- */
- void disconnect();
-
- /**
- * @return true if a local echo is needed.
- * TODO:Michael Scharf: this should be handed within the connection....
- */
- boolean isLocalEcho();
-
- /**
- * Notify the remote site that the size of the terminal has changed.
- * @param newWidth
- * @param newHeight
- */
- void setTerminalSize(int newWidth, int newHeight);
-
- /**
- * @return the terminal to remote stream (bytes written to this stream will
- * be sent to the remote site). For the stream in the other direction (remote to
- * terminal see {@link ITerminalControl#getRemoteToTerminalOutputStream()}
- * @since org.eclipse.tm.terminal 2.0
- */
- OutputStream getTerminalToRemoteStream();
-
- /**
- * Load the state of this connection. Is typically called before
- * {@link #connect(ITerminalControl)}.
- *
- * @param store a string based data store. Short keys like "foo" can be used to
- * store the state of the connection.
- */
- void load(ISettingsStore store);
-
- /**
- * When the view or dialog containing the terminal is closed,
- * the state of the connection is saved into the settings store <code>store</code>
- * @param store
- */
- void save(ISettingsStore store);
-
- /**
- * FIXME should not have UI related stuff in ITerminalConnector, since
- * connectors may be totally programmatic and UI-less. Better make the
- * connector adapt to an interface that controls the UI aspect.
- *
- * @return a new page that can be used in a dialog to setup this connection.
- * The dialog should persist its settings with the
- * {@link #load(ISettingsStore)} and {@link #save(ISettingsStore)}
- * methods.
- */
- ISettingsPage makeSettingsPage();
-
- /**
- * @return A string that represents the settings of the connection. This representation
- * may be shown in the status line of the terminal view.
- */
- String getSettingsSummary();
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java
deleted file mode 100644
index cf555cd..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use
- * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Shell;
-
-/**
- * Represents the terminal view as seen by a terminal connection.
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
- * of a work in progress. There is no guarantee that this API will work or that
- * it will remain the same. Please do not use this API without consulting with
- * the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- *
- * @author Michael Scharf
- * @noimplement This interface is not intended to be implemented by clients.
- * @noextend This interface is not intended to be extended by clients.
- */
-public interface ITerminalControl {
-
- /**
- * @return the current state of the connection
- */
- TerminalState getState();
-
- /**
- * @param state
- */
- void setState(TerminalState state);
-
- /**
- * Setup the terminal control within the given parent composite.
- *
- * @param parent The parent composite. Must not be <code>null</code>.
- */
- void setupTerminal(Composite parent);
-
- /**
- * A shell to show dialogs.
- * @return the shell in which the terminal is shown.
- */
- Shell getShell();
-
- /**
- * Set the encoding that the Terminal uses to decode bytes from the
- * Terminal-to-remote-Stream into Unicode Characters used in Java; or, to
- * encode Characters typed by the user into bytes sent over the wire to the
- * remote.
- *
- * By default, the local Platform Default Encoding is used. Also note that
- * the encoding must not be applied in case the terminal stream is processed
- * by some data transfer protocol which requires binary data.
- *
- * Validity of the encoding set here is not checked. Since some encodings do
- * not cover the entire range of Unicode characters, it can happen that a
- * particular Unicode String typed in by the user can not be encoded into a
- * byte Stream with the encoding specified. and UnsupportedEncodingException
- * will be thrown in this case at the time the String is about to be
- * processed.
- *
- * The concrete encoding to use can either be specified manually by a user,
- * by means of a dialog, or a connector can try to obtain it automatically
- * from the remote side e.g. by evaluating an environment variable such as
- * LANG on UNIX systems.
- *
- * @since org.eclipse.tm.terminal 2.0
- */
- void setEncoding(String encoding) throws UnsupportedEncodingException;
-
- /**
- * Return the current encoding. That's interesting when the previous
- * setEncoding() call failed and the fallback default encoding should be
- * queried, such that e.g. a combobox with encodings to choose can be
- * properly initialized.
- *
- * @return the current Encoding of the Terminal.
- * @since org.eclipse.tm.terminal 2.0
- */
- String getEncoding();
-
- /**
- * Show a text in the terminal. If puts newlines at the beginning and the
- * end.
- *
- * @param text TODO: Michael Scharf: Is this really needed?
- */
- void displayTextInTerminal(String text);
-
- /**
- * @return a stream used to write to the terminal. Any bytes written to this
- * stream appear in the terminal or are interpreted by the emulator as
- * control sequences. The stream in the opposite direction, terminal
- * to remote is in {@link ITerminalConnector#getTerminalToRemoteStream()}.
- */
- OutputStream getRemoteToTerminalOutputStream();
-
- /**
- * Set the title of the terminal view.
- * @param title
- */
- void setTerminalTitle(String title);
-
- /**
- * Show an error message during connect.
- * @param msg
- * TODO: Michael Scharf: Should be replaced by a better error notification mechanism!
- */
- void setMsg(String msg);
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/LayeredSettingsStore.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/LayeredSettingsStore.java
deleted file mode 100644
index 8559224..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/LayeredSettingsStore.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-/**
- * Uses an array of {@link ISettingsStore} to find a value.
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
- * of a work in progress. There is no guarantee that this API will work or that
- * it will remain the same. Please do not use this API without consulting with
- * the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public class LayeredSettingsStore implements ISettingsStore {
-
- private final ISettingsStore[] fStores;
-
- /**
- * @param stores the stores used to search the values.
- * {@link #put(String, String)} will put the value in the
- * first store in the list.
- */
- public LayeredSettingsStore(ISettingsStore[] stores) {
- fStores=stores;
- }
- /**
- * Convince constructor for two stores
- * @param s1 first store
- * @param s2 second store
- */
- public LayeredSettingsStore(ISettingsStore s1, ISettingsStore s2) {
- this(new ISettingsStore[]{s1,s2});
- }
- public String get(String key) {
- for (int i = 0; i < fStores.length; i++) {
- String value=fStores[i].get(key);
- if(value!=null)
- return value;
- }
- return null;
- }
-
- public String get(String key, String defaultValue) {
- String value=get(key);
- if ((value == null) || (value.equals(""))) //$NON-NLS-1$
- return defaultValue;
- return value;
- }
-
- public void put(String key, String value) {
- fStores[0].put(key,value);
- }
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/Logger.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/Logger.java
deleted file mode 100644
index fa6fee9..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/Logger.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Fran Litterio (Wind River) - initial API and implementation
- * Ted Williams (Wind River) - refactored into org.eclipse namespace
- * Michael Scharf (Wind River) - split into core, view and connector plugins
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
-
-/**
- * A simple logger class. Every method in this class is static, so they can be
- * called from both class and instance methods. To use this class, write code
- * like this:
- * <p>
- *
- * <pre>
- * Logger.log("something has happened");
- * Logger.log("counter is " + counter);
- * </pre>
- *
- * @author Fran Litterio <francis.litterio@windriver.com>
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
- * part of a work in progress. There is no guarantee that this API will
- * work or that it will remain the same. Please do not use this API without
- * consulting with the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public final class Logger {
- public static final String TRACE_DEBUG_LOG = "org.eclipse.tm.terminal/debug/log"; //$NON-NLS-1$
- public static final String TRACE_DEBUG_LOG_ERROR = "org.eclipse.tm.terminal/debug/log/error"; //$NON-NLS-1$
- public static final String TRACE_DEBUG_LOG_INFO = "org.eclipse.tm.terminal/debug/log/info"; //$NON-NLS-1$
- public static final String TRACE_DEBUG_LOG_CHAR = "org.eclipse.tm.terminal/debug/log/char"; //$NON-NLS-1$
- public static final String TRACE_DEBUG_LOG_BUFFER_SIZE = "org.eclipse.tm.terminal/debug/log/buffer/size"; //$NON-NLS-1$
-
- private static PrintStream logStream;
-
- static {
- String logFile = null;
- //TODO I think this should go into the workspace metadata instead.
- File logDirWindows = new File("C:\\eclipselogs"); //$NON-NLS-1$
- File logDirUNIX = new File("/tmp/eclipselogs"); //$NON-NLS-1$
-
- if (logDirWindows.isDirectory()) {
- logFile = logDirWindows + "\\tmterminal.log"; //$NON-NLS-1$
- } else if (logDirUNIX.isDirectory()) {
- logFile = logDirUNIX + "/tmterminal.log"; //$NON-NLS-1$
- }
-
- if (logFile != null) {
- try {
- logStream = new PrintStream(new FileOutputStream(logFile, true));
- } catch (Exception ex) {
- logStream = System.err;
- logStream
- .println("Exception when opening log file -- logging to stderr!"); //$NON-NLS-1$
- ex.printStackTrace(logStream);
- }
- }
- }
-
- /**
- * Encodes a String such that non-printable control characters are
- * converted into user-readable escape sequences for logging.
- * @param message String to encode
- * @return encoded String
- */
- public static final String encode(String message) {
- boolean encoded = false;
- StringBuffer buf = new StringBuffer(message.length()+32);
- for (int i=0; i<message.length(); i++) {
- char c=message.charAt(i);
- switch(c) {
- case '\\':
- case '\'':
- buf.append('\\'); buf.append(c); encoded=true;
- break;
- case '\r':
- buf.append('\\'); buf.append('r'); encoded=true;
- break;
- case '\n':
- buf.append('\\'); buf.append('n'); encoded=true;
- break;
- case '\t':
- buf.append('\\'); buf.append('t'); encoded=true;
- break;
- case '\f':
- buf.append('\\'); buf.append('f'); encoded=true;
- break;
- case '\b':
- buf.append('\\'); buf.append('b'); encoded=true;
- break;
- default:
- if (c <= '\u000f') {
- buf.append('\\'); buf.append('x'); buf.append('0');
- buf.append(Integer.toHexString(c));
- encoded=true;
- } else if (c>=' ' && c<'\u007f') {
- buf.append(c);
- } else if (c <= '\u00ff') {
- buf.append('\\'); buf.append('x');
- buf.append(Integer.toHexString(c));
- encoded=true;
- } else {
- buf.append('\\'); buf.append('u');
- if (c<='\u0fff') {
- buf.append('0');
- }
- buf.append(Integer.toHexString(c));
- encoded=true;
- }
- }
- }
- if (encoded) {
- return buf.toString();
- }
- return message;
- }
-
- /**
- * Checks if logging is enabled.
- * @return true if logging is enabled.
- */
- public static final boolean isLogEnabled() {
- return (logStream!=null);
- }
-
- /**
- * Logs the specified message. Do not append a newline to parameter
- * <i>message</i>. This method does that for you.
- *
- * @param message A String containing the message to log.
- */
- public static final void log(String message) {
- if (logStream != null) {
- // Read my own stack to get the class name, method name, and line
- // number of
- // where this method was called.
-
- StackTraceElement caller = new Throwable().getStackTrace()[1];
- int lineNumber = caller.getLineNumber();
- String className = caller.getClassName();
- String methodName = caller.getMethodName();
- className = className.substring(className.lastIndexOf('.') + 1);
-
- logStream.println(className + "." + methodName + ":" + lineNumber + ": " + message); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
- logStream.flush();
- }
- }
-
- /**
- * Writes a stack trace for an exception to both Standard Error and to the
- * log file.
- */
- public static final void logException(Exception ex) {
- // log in eclipse error log
- if (TerminalPlugin.getDefault() != null) {
- TerminalPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TerminalPlugin.PLUGIN_ID, IStatus.OK, ex.getMessage(), ex));
- } else {
- ex.printStackTrace();
- }
- // Additional Tracing for debug purposes:
- // Read my own stack to get the class name, method name, and line number
- // of where this method was called
- if(logStream!=null) {
- StackTraceElement caller = new Throwable().getStackTrace()[1];
- int lineNumber = caller.getLineNumber();
- String className = caller.getClassName();
- String methodName = caller.getMethodName();
- className = className.substring(className.lastIndexOf('.') + 1);
-
- PrintStream tmpStream = System.err;
-
- if (logStream != null) {
- tmpStream = logStream;
- }
-
- tmpStream.println(className
- + "." + methodName + ":" + lineNumber + ": " + //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
- "Caught exception: " + ex); //$NON-NLS-1$
- ex.printStackTrace(tmpStream);
- }
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/PreferenceSettingStore.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/PreferenceSettingStore.java
deleted file mode 100644
index ff0e6f8..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/PreferenceSettingStore.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-import org.eclipse.core.runtime.Preferences;
-
-/**
- * A preference based settings store.
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
- * of a work in progress. There is no guarantee that this API will work or that
- * it will remain the same. Please do not use this API without consulting with
- * the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public class PreferenceSettingStore implements ISettingsStore {
- private final String fPrefix;
- private final Preferences fPreferences;
-
- /**
- * Creates a ISettingStore that uses the preferences as backend.
- *
- * @param preferences the backed.
- * @param prefix a string that is prepended to the key
- */
- public PreferenceSettingStore(Preferences preferences, String prefix) {
- fPreferences=preferences;
- fPrefix=prefix;
- }
- public String get(String key) {
- return fPreferences.getString(makeKey(key));
- }
- public String get(String key, String defaultValue) {
- String value=get(key);
- if ((value == null) || (value.equals(""))) //$NON-NLS-1$
- return defaultValue;
-
- return value;
- }
-
- public void put(String key, String value) {
- fPreferences.setValue(makeKey(key), value);
- }
- /**
- * @param key
- * @return the full path in the preferences
- */
- private String makeKey(String key) {
- return fPrefix+key;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/TerminalConnectorExtension.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/TerminalConnectorExtension.java
deleted file mode 100644
index ed2f80f..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/TerminalConnectorExtension.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Uwe Stieber (Wind River) - [282996] [terminal][api] Add "hidden" attribute to terminal connector extension point
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.RegistryFactory;
-import org.eclipse.tm.internal.terminal.connector.TerminalConnector;
-import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
-
-/**
- * A factory to get {@link ITerminalConnector} instances.
- *
- * @author Michael Scharf
- *
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- *
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
- * part of a work in progress. There is no guarantee that this API will work or
- * that it will remain the same. Please do not use this API without consulting
- * with the <a href="http://www.eclipse.org/tm/">Target Management</a>
- * team.
- * </p>
- */
-public class TerminalConnectorExtension {
- static private ITerminalConnector makeConnector(final IConfigurationElement config) {
- String id = config.getAttribute("id"); //$NON-NLS-1$
- if(id==null || id.length()==0)
- id=config.getAttribute("class"); //$NON-NLS-1$
- String name= config.getAttribute("name"); //$NON-NLS-1$
- if(name==null || name.length()==0) {
- name=id;
- }
- String hidden = config.getAttribute("hidden"); //$NON-NLS-1$
- boolean isHidden = hidden != null ? new Boolean(hidden).booleanValue() : false;
- TerminalConnector.Factory factory=new TerminalConnector.Factory(){
- public TerminalConnectorImpl makeConnector() throws Exception {
- return (TerminalConnectorImpl)config.createExecutableExtension("class"); //$NON-NLS-1$
- }};
- return new TerminalConnector(factory,id,name, isHidden);
- }
-
- /**
- * Return a specific terminal connector for a given connector id. The
- * terminal connector is not yet instantiated to any real connection.
- *
- * @param id the id of the terminal connector in the
- * <code>org.eclipse.tm.terminal.terminalConnectors</code>
- * extension point
- * @return a new ITerminalConnector with id or <code>null</code> if there
- * is no extension with that id.
- * @since org.eclipse.tm.terminal 2.0
- */
- public static ITerminalConnector makeTerminalConnector(String id) {
- IConfigurationElement[] config = RegistryFactory.getRegistry().getConfigurationElementsFor("org.eclipse.tm.terminal.terminalConnectors"); //$NON-NLS-1$
- for (int i = 0; i < config.length; i++) {
- if(id.equals(config[i].getAttribute("id"))) { //$NON-NLS-1$
- return makeConnector(config[i]);
- }
- }
- return null;
- }
- /**
- * Return a list of available terminal connectors (connection types).
- *
- * The terminal connectors returned are not yet instantiated to any real
- * connection. Each terminal connector can connect to one remote system at a
- * time.
- *
- * @return a new list of {@link ITerminalConnector} instances defined in the
- * <code>org.eclipse.tm.terminal.terminalConnectors</code>
- * extension point
- * @since org.eclipse.tm.terminal 2.0 return value is ITerminalConnector[]
- */
- public static ITerminalConnector[] makeTerminalConnectors() {
- IConfigurationElement[] config = RegistryFactory.getRegistry().getConfigurationElementsFor("org.eclipse.tm.terminal.terminalConnectors"); //$NON-NLS-1$
- List result=new ArrayList();
- for (int i = 0; i < config.length; i++) {
- result.add(makeConnector(config[i]));
- }
- return (ITerminalConnector[]) result.toArray(new ITerminalConnector[result.size()]);
- }
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/TerminalState.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/TerminalState.java
deleted file mode 100644
index c0886a6..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/TerminalState.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
- * Michael Scharf (Wind River) - [262996] get rid of TerminalState.OPENED
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api;
-
-/**
- * Represent the sate of a terminal connection.
- * In java 1.5 this would be an enum.
- * @author Michael Scharf
- *
- * <p>
- * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
- * part of a work in progress. There is no guarantee that this API will
- * work or that it will remain the same. Please do not use this API without
- * consulting with the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
- * </p>
- */
-public class TerminalState {
- /**
- * The terminal is not connected.
- */
- public final static TerminalState CLOSED=new TerminalState("CLOSED"); //$NON-NLS-1$
-
- /**
- * The terminal is about to connect.
- */
- public final static TerminalState CONNECTING=new TerminalState("CONNECTING..."); //$NON-NLS-1$
-
- /**
- * The terminal is connected.
- */
- public final static TerminalState CONNECTED=new TerminalState("CONNECTED"); //$NON-NLS-1$
-
- private final String fState;
-
- public TerminalState(String state) {
- fState = state;
- }
-
- public String toString() {
- return fState;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorImpl.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorImpl.java
deleted file mode 100644
index 27e5557..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorImpl.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.provisional.api.provider;
-
-import java.io.OutputStream;
-
-import org.eclipse.tm.internal.terminal.provisional.api.ISettingsPage;
-import org.eclipse.tm.internal.terminal.provisional.api.ISettingsStore;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
-import org.eclipse.tm.internal.terminal.provisional.api.Logger;
-import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-
-/**
- * Abstract base class for all terminal connector implementations to be
- * registered via the <code>org.eclipse.tm.terminal.terminalConnectors</code>
- * extension point.
- *
- * @since org.eclipse.tm.terminal 2.0
- */
-public abstract class TerminalConnectorImpl {
-
- /**
- * The TerminalControl associated with this connector.
- * Required for advertising state changes when needed.
- */
- protected ITerminalControl fControl;
-
- /**
- * Initialize this connector. This is called once after the constructor, in
- * order to perform any required initializations such as loading required
- * native libraries. Any work that may lead to runtime exceptions should be
- * done in this method rather than in the constructor.
- *
- * @throws Exception when the connector fails to initialize (due to missing
- * required libraries, for instance).
- */
- public void initialize() throws Exception {
- }
-
- /**
- * Connect using the current state of the settings.
- *
- * This method is designed to be overridden by actual implementations, in
- * order to open the streams required for communicating with the remote
- * side. Extenders must call <code>super.connect(control)</code> as the
- * first thing they are doing.
- *
- * @param control Used to inform the UI about state changes and messages
- * from the connection.
- */
- public void connect(ITerminalControl control) {
- Logger.log("entered."); //$NON-NLS-1$
- fControl = control;
- }
-
- /**
- * Disconnect if connected. Else do nothing. Has to set the state of the
- * {@link ITerminalControl} when finished disconnecting.
- */
- public final void disconnect() {
- Logger.log("entered."); //$NON-NLS-1$
- doDisconnect();
- fControl.setState(TerminalState.CLOSED);
- }
-
- /**
- * Disconnect if connected. Else do nothing. Clients should override to
- * perform any extra work needed for disconnecting.
- */
- protected void doDisconnect() {
- // Do nothing by default
- }
-
- /**
- * @return the terminal to remote stream (bytes written to this stream will
- * be sent to the remote site). For the stream in the other direction (remote to
- * terminal see {@link ITerminalControl#getRemoteToTerminalOutputStream()}
- */
- abstract public OutputStream getTerminalToRemoteStream();
-
- /**
- * @return A string that represents the settings of the connection. This representation
- * may be shown in the status line of the terminal view.
- */
- abstract public String getSettingsSummary();
-
- /**
- * Test if local echo is needed. The default implementation returns
- * <code>false</code>. Override to modify this behavior.
- *
- * @return true if a local echo is needed. TODO:Michael Scharf: this should
- * be handed within the connection....
- */
- public boolean isLocalEcho() {
- return false;
- }
-
- /**
- * Return a settings page for configuring this connector, or
- * <code>null</code> if it cannot be configured.
- *
- * The dialog should persist its settings with the
- * {@link #load(ISettingsStore)} and {@link #save(ISettingsStore)} methods.
- *
- * @return a new page that can be used in a dialog to setup this connection,
- * or <code>null</code>.
- */
- public ISettingsPage makeSettingsPage() {
- return null;
- }
-
- /**
- * Load the state or settings of this connection. Is typically called before
- * {@link #connect(ITerminalControl)}.
- *
- * Connectors that have nothing to configure do not need to implement this.
- * Those terminals that do have configuration (which they expose via
- * {@link #makeSettingsPage()} need to override this method to load
- * settings.
- *
- * @param store a string based data store. Short keys like "foo" can be used
- * to store the state of the connection.
- */
- public void load(ISettingsStore store) {
- // do nothing by default
- }
-
- /**
- * When the view or dialog containing the terminal is closed, the state of
- * the connection is saved into the settings store <code>store</code>.
- *
- * Connectors that have no state or settings to persist do not need to
- * override this. Others should override to persist their settings.
- *
- * @param store the store for persisting settings.
- */
- public void save(ISettingsStore store) {
- // do nothing by default
- }
-
- /**
- * Notify the remote site that the size of the terminal has changed.
- *
- * Concrete connectors should override this if they have the possibility to
- * inform the remote about changed terminal size.
- *
- * @param newWidth the new width in characters.
- * @param newHeight the new height in characters.
- */
- public void setTerminalSize(int newWidth, int newHeight) {
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/AbstractTextCanvasModel.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/AbstractTextCanvasModel.java
deleted file mode 100644
index 770db97..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/AbstractTextCanvasModel.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - [168197] Fix Terminal for CDC-1.1/Foundation-1.1
- * Anton Leherbauer (Wind River) - [219589] Copy an entire line selection
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-
-abstract public class AbstractTextCanvasModel implements ITextCanvasModel {
- protected List fListeners = new ArrayList();
- private int fCursorLine;
- private int fCursorColumn;
- private boolean fShowCursor;
- private long fCursorTime;
- private boolean fCursorIsEnabled;
- private final ITerminalTextDataSnapshot fSnapshot;
- private int fLines;
-
- private int fSelectionStartLine=-1;
- private int fSeletionEndLine;
- private int fSelectionStartCoumn;
- private int fSelectionEndColumn;
- private ITerminalTextDataSnapshot fSelectionSnapshot;
- private String fCurrentSelection=""; //$NON-NLS-1$
- private final Point fSelectionAnchor=new Point(0,0);
- /**
- * do not update while update is running
- */
- boolean fInUpdate;
- private int fCols;
-
- public AbstractTextCanvasModel(ITerminalTextDataSnapshot snapshot) {
- fSnapshot=snapshot;
- fLines=fSnapshot.getHeight();
- }
- public void addCellCanvasModelListener(ITextCanvasModelListener listener) {
- fListeners.add(listener);
- }
-
- public void removeCellCanvasModelListener(ITextCanvasModelListener listener) {
- fListeners.remove(listener);
- }
-
- protected void fireCellRangeChanged(int x, int y, int width, int height) {
- for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
- ITextCanvasModelListener listener = (ITextCanvasModelListener) iter.next();
- listener.rangeChanged(x, y, width, height);
- }
- }
- protected void fireDimensionsChanged( int width,int height) {
- for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
- ITextCanvasModelListener listener = (ITextCanvasModelListener) iter.next();
- listener.dimensionsChanged(width,height);
- }
-
- }
- protected void fireTerminalDataChanged() {
- for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
- ITextCanvasModelListener listener = (ITextCanvasModelListener) iter.next();
- listener.terminalDataChanged();
- }
-
- }
-
- public ITerminalTextDataReadOnly getTerminalText() {
- return fSnapshot;
- }
- protected ITerminalTextDataSnapshot getSnapshot() {
- return fSnapshot;
- }
- protected void updateSnapshot() {
- if(!fInUpdate && fSnapshot.isOutOfDate()) {
- fInUpdate=true;
- try {
- fSnapshot.updateSnapshot(false);
- if(fSnapshot.hasTerminalChanged())
- fireTerminalDataChanged();
- // TODO why does hasDimensionsChanged not work??????
- // if(fSnapshot.hasDimensionsChanged())
- // fireDimensionsChanged();
- if(fLines!=fSnapshot.getHeight() || fCols!=fSnapshot.getWidth()) {
- fireDimensionsChanged(fSnapshot.getWidth(),fSnapshot.getHeight());
- fLines=fSnapshot.getHeight();
- fCols=fSnapshot.getWidth();
- }
- int y=fSnapshot.getFirstChangedLine();
- // has any line changed?
- if(y<Integer.MAX_VALUE) {
- int height=fSnapshot.getLastChangedLine()-y+1;
- fireCellRangeChanged(0, y, fSnapshot.getWidth(), height);
- }
-
- } finally {
- fInUpdate=false;
- }
- }
- }
- /**
- * must be called from the UI thread
- */
- public void update() {
- // do the poll....
- updateSnapshot();
- updateSelection();
- updateCursor();
- }
-
-
- public int getCursorColumn() {
- return fCursorColumn;
- }
-
- public int getCursorLine() {
- return fCursorLine;
- }
-
- public boolean isCursorOn() {
- return fShowCursor && fCursorIsEnabled;
- }
- /**
- * should be called regularly to draw an update of the
- * blinking cursor
- */
- protected void updateCursor() {
- if(!fCursorIsEnabled)
- return;
- int cursorLine=getSnapshot().getCursorLine();
- int cursorColumn=getSnapshot().getCursorColumn();
- // if cursor at the end put it to the end of the
- // last line...
- if(cursorLine>=getSnapshot().getHeight()) {
- cursorLine=getSnapshot().getHeight()-1;
- cursorColumn=getSnapshot().getWidth()-1;
- }
- // has the cursor moved?
- if(fCursorLine!=cursorLine || fCursorColumn!=cursorColumn) {
- // hide the old cursor!
- fShowCursor=false;
- // clean the previous cursor
- // bug 206363: paint also the char to the left and right of the cursor - see also below
- int col=fCursorColumn;
- int width=2;
- if(col>0) {
- col--;
- width++;
- }
- fireCellRangeChanged(col, fCursorLine, width, 1);
- // the cursor is shown when it moves!
- fShowCursor=true;
- fCursorTime=System.currentTimeMillis();
- fCursorLine=cursorLine;
- fCursorColumn=cursorColumn;
- // and draw the new cursor
- fireCellRangeChanged(fCursorColumn, fCursorLine, 1, 1);
- } else {
- long t=System.currentTimeMillis();
- // TODO make the cursor blink time customisable
- if(t-fCursorTime>500) {
- fShowCursor=!fShowCursor;
- fCursorTime=t;
- // on some windows machines, there is some left
- // over when updating the cursor .
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=206363
- int col=fCursorColumn;
- int width=2;
- if(col>0) {
- col--;
- width++;
- }
- fireCellRangeChanged(col, fCursorLine, width, 1);
- }
- }
- }
- public void setVisibleRectangle(int startLine, int startCol, int height, int width) {
- fSnapshot.setInterestWindow(Math.max(0,startLine), Math.max(1,height));
- update();
- }
- protected void showCursor(boolean show) {
- fShowCursor=true;
- }
- public void setCursorEnabled(boolean visible) {
- fCursorTime=System.currentTimeMillis();
- fShowCursor=visible;
- fCursorIsEnabled=visible;
- fireCellRangeChanged(fCursorColumn, fCursorLine, 1, 1);
- }
- public boolean isCursorEnabled() {
- return fCursorIsEnabled;
- }
-
- public Point getSelectionEnd() {
- if(fSelectionStartLine<0)
- return null;
- else
- return new Point(fSelectionEndColumn, fSeletionEndLine);
- }
-
- public Point getSelectionStart() {
- if (fSelectionStartLine < 0)
- return null;
- else
- return new Point(fSelectionStartCoumn,fSelectionStartLine);
- }
- public Point getSelectionAnchor() {
- if(fSelectionStartLine<0)
- return null;
- return new Point(fSelectionAnchor.x,fSelectionAnchor.y);
- }
- public void setSelectionAnchor(Point anchor) {
- fSelectionAnchor.x=anchor.x;
- fSelectionAnchor.y=anchor.y;
- }
-
- public void setSelection(int startLine, int endLine, int startColumn, int endColumn) {
-// System.err.println(startLine+","+endLine+","+startColumn+","+endColumn);
- doSetSelection(startLine, endLine, startColumn, endColumn);
- fCurrentSelection=extractSelectedText();
- }
- private void doSetSelection(int startLine, int endLine, int startColumn, int endColumn) {
- assert(startLine<0 || startLine<=endLine);
- if(startLine>=0) {
- if(fSelectionSnapshot==null) {
- fSelectionSnapshot=fSnapshot.getTerminalTextData().makeSnapshot();
- fSelectionSnapshot.updateSnapshot(true);
- }
- } else if(fSelectionSnapshot!=null) {
- fSelectionSnapshot.detach();
- fSelectionSnapshot=null;
- }
- int oldStart=fSelectionStartLine;
- int oldEnd=fSeletionEndLine;
- fSelectionStartLine = startLine;
- fSeletionEndLine = endLine;
- fSelectionStartCoumn = startColumn;
- fSelectionEndColumn = endColumn;
- if(fSelectionSnapshot!=null) {
- fSelectionSnapshot.setInterestWindow(0, fSelectionSnapshot.getHeight());
- }
- int changedStart;
- int changedEnd;
- if(oldStart<0) {
- changedStart=fSelectionStartLine;
- changedEnd=fSeletionEndLine;
- } else if(fSelectionStartLine<0) {
- changedStart=oldStart;
- changedEnd=oldEnd;
- } else {
- changedStart=Math.min(oldStart, fSelectionStartLine);
- changedEnd=Math.max(oldEnd, fSeletionEndLine);
- }
- if(changedStart>=0) {
- fireCellRangeChanged(0, changedStart, fSnapshot.getWidth(), changedEnd-changedStart+1);
- }
- }
-
- public boolean hasLineSelection(int line) {
- if (fSelectionStartLine < 0)
- return false;
- else
- return line >= fSelectionStartLine && line <= fSeletionEndLine;
- }
-
- public String getSelectedText() {
- return fCurrentSelection;
- }
- /**
- * Calculates the currently selected text
- * @return the currently selected text
- */
- private String extractSelectedText() {
- if(fSelectionStartLine<0 || fSelectionStartCoumn<0 || fSelectionSnapshot==null)
- return ""; //$NON-NLS-1$
- StringBuffer buffer=new StringBuffer();
- for (int line = fSelectionStartLine; line <= fSeletionEndLine; line++) {
- String text;
- char[] chars=fSelectionSnapshot.getChars(line);
- if(chars!=null) {
- text=new String(chars);
- if(line==fSeletionEndLine && fSelectionEndColumn >= 0)
- text=text.substring(0, Math.min(fSelectionEndColumn+1,text.length()));
- if(line==fSelectionStartLine)
- text=text.substring(Math.min(fSelectionStartCoumn,text.length()));
- // get rid of the empty space at the end of the lines
- // text=text.replaceAll("\000+$",""); //$NON-NLS-1$//$NON-NLS-2$
- // <J2ME-CDC-1.1 version>
- int i = text.length() - 1;
- while (i >= 0 && text.charAt(i) == '\000') {
- i--;
- }
- text = text.substring(0, i + 1);
- // </J2ME-CDC-1.1 version>
- // null means space
- text=text.replace('\000', ' ');
- } else {
- text=""; //$NON-NLS-1$
- }
- buffer.append(text);
- if(line < fSeletionEndLine)
- buffer.append('\n');
- }
- return buffer.toString();
- }
- private void updateSelection() {
- if (fSelectionSnapshot != null && fSelectionSnapshot.isOutOfDate()) {
- fSelectionSnapshot.updateSnapshot(true);
- // has the selection moved?
- if (fSelectionSnapshot != null && fSelectionStartLine >= 0 && fSelectionSnapshot.getScrollWindowSize() > 0) {
- int start = fSelectionStartLine + fSelectionSnapshot.getScrollWindowShift();
- int end = fSeletionEndLine + fSelectionSnapshot.getScrollWindowShift();
- if (start < 0)
- if (end >= 0)
- start = 0;
- else
- start = -1;
- doSetSelection(start, end, fSelectionStartCoumn, fSelectionEndColumn);
- }
- // check if the content of the selection has changed. If the content has
- // changed, clear the selection
- if (fCurrentSelection.length()>0 && fSelectionSnapshot != null
- && fSelectionSnapshot.getFirstChangedLine() <= fSeletionEndLine
- && fSelectionSnapshot.getLastChangedLine() >= fSelectionStartLine) {
- // has the selected text changed?
- if (!fCurrentSelection.equals(extractSelectedText())) {
- setSelection(-1, -1, -1, -1);
- }
- }
- // update the observed window...
- if (fSelectionSnapshot != null)
- // todo make -1 to work!
- fSelectionSnapshot.setInterestWindow(0, fSelectionSnapshot.getHeight());
- }
- }
-
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/GridCanvas.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/GridCanvas.java
deleted file mode 100644
index 8c24097..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/GridCanvas.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Anton Leherbauer (Wind River) - [294468] Fix scroller and text line rendering
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.ScrollBar;
-
-/**
- * A Grid based Canvas. The canvas has rows and columns.
- * CellPainting is done with the abstract method drawCell
- */
-abstract public class GridCanvas extends VirtualCanvas {
- /** width of a cell */
- private int fCellWidth;
- /** height of a cell */
- private int fCellHeight;
-
- public GridCanvas(Composite parent, int style) {
- super(parent, style);
- addListener(SWT.MouseWheel, new Listener() {
- public void handleEvent(Event event) {
- if(getVerticalBar().isVisible()) {
- int delta=-fCellHeight;
- if(event.count<0)
- delta=-delta;
- scrollYDelta(delta);
- }
- event.doit=false;
- }
- });
-
- }
-
- /** template method paint.
- * iterates over all cells in the clipping rectangle and paints them.
- */
- protected void paint(GC gc) {
- Rectangle clipping=gc.getClipping();
- if(clipping.width==0 || clipping.height==0)
- return;
- Rectangle clientArea= getScreenRectInVirtualSpace();
- // Beginning coordinates
- int xOffset=clientArea.x;
- int yOffset=clientArea.y;
- int colFirst=virtualXToCell(xOffset+clipping.x);
- if(colFirst>getCols())
- colFirst=getCols();
- else if (colFirst < 0) {
- colFirst = 0;
- }
- int rowFirst=virtualYToCell(yOffset+clipping.y);
- // End coordinates
- int colLast=virtualXToCell(xOffset+clipping.x+clipping.width+fCellWidth);
- if(colLast>getCols())
- colLast=getCols();
- int rowLast=virtualYToCell(yOffset+clipping.y+clipping.height+fCellHeight);
- if(rowLast>getRows())
- rowLast=getRows();
- // System.out.println(rowFirst+"->"+rowLast+" "+System.currentTimeMillis());
- // draw the cells
- for(int row=rowFirst;row<=rowLast;row++) {
- int cx=colFirst*fCellWidth-xOffset;
- int cy=row*fCellHeight-yOffset;
- drawLine(gc,row,cx,cy,colFirst,colLast);
- }
- paintUnoccupiedSpace(gc,clipping);
- }
- /**
- * @param gc
- * @param row the line to draw
- * @param x coordinate on screen
- * @param y coordinate on screen
- * @param colFirst first column to draw
- * @param colLast last column to draw
- */
- abstract void drawLine(GC gc, int row, int x, int y, int colFirst, int colLast);
-
- abstract protected int getRows();
- abstract protected int getCols();
-
- protected void setCellWidth(int cellWidth) {
- fCellWidth = cellWidth;
- getHorizontalBar().setIncrement(fCellWidth);
- }
-
- public int getCellWidth() {
- return fCellWidth;
- }
-
- protected void setCellHeight(int cellHeight) {
- fCellHeight = cellHeight;
- getVerticalBar().setIncrement(fCellHeight);
- }
-
- public int getCellHeight() {
- return fCellHeight;
- }
-
- int virtualXToCell(int x) {
- return x/fCellWidth;
- }
-
- int virtualYToCell(int y) {
- return y/fCellHeight;
- }
-
- protected Point screenPointToCell(int x, int y) {
- x=screenXtoVirtual(x)/fCellWidth;
- y=screenYtoVirtual(y)/fCellHeight;
- return new Point(x,y);
- }
-
- Point screenPointToCell(Point point) {
- return screenPointToCell(point.x,point.y);
- }
-
- protected Point cellToOriginOnScreen(int x, int y) {
- x=virtualXtoScreen(fCellWidth*x);
- y=virtualYtoScreen(fCellHeight*y);
- return new Point(x,y);
- }
-
- Point cellToOriginOnScreen(Point cell) {
- return cellToOriginOnScreen(cell.x,cell.y);
- }
-
- Rectangle getCellScreenRect(Point cell) {
- return getCellScreenRect(cell.x,cell.y);
- }
-
- Rectangle getCellScreenRect(int x, int y) {
- x=fCellWidth*virtualXtoScreen(x);
- y=fCellHeight*virtualYtoScreen(y);
- return new Rectangle(x,y,fCellWidth,fCellHeight);
- }
-
- protected Rectangle getCellVirtualRect(Point cell) {
- return getCellVirtualRect(cell.x,cell.y);
- }
-
- Rectangle getCellVirtualRect(int x, int y) {
- x=fCellWidth*x;
- y=fCellHeight*y;
- return new Rectangle(x,y,fCellWidth,fCellHeight);
- }
- protected void viewRectangleChanged(int x, int y, int width, int height) {
- int cellX=virtualXToCell(x);
- int cellY=virtualYToCell(y);
- // End coordinates
- int xE=virtualXToCell(x+width);
-// if(xE>getCols())
-// xE=getCols();
- int yE=virtualYToCell(y+height);
-// if(yE>getRows())
-// yE=getRows();
- visibleCellRectangleChanged(cellX,cellY,xE-cellX,yE-cellY);
- }
-
- /**
- * Called when the viewed part has changed.
- * Override when you need this information....
- * Is only called if the values change (well, almost)
- * @param x origin of visible cells
- * @param y origin of visible cells
- * @param width number of cells visible in x direction
- * @param height number of cells visible in y direction
- */
- protected void visibleCellRectangleChanged(int x, int y, int width, int height) {
- }
-
- protected void setVirtualExtend(int width, int height) {
- int cellHeight = getCellHeight();
- if (cellHeight > 0) {
- height -= height % cellHeight;
- }
- super.setVirtualExtend(width, height);
- }
-
- protected void setVirtualOrigin(int x, int y) {
- int cellHeight = getCellHeight();
- if (cellHeight > 0) {
- int remainder = y % cellHeight;
- if (remainder < 0) {
- y -= (cellHeight + remainder);
- } else {
- y -= remainder;
- }
- }
- super.setVirtualOrigin(x, y);
- }
-
- protected void scrollY(ScrollBar vBar) {
- int vSelection = vBar.getSelection ();
- Rectangle bounds = getVirtualBounds();
- int y = -vSelection;
- int cellHeight = getCellHeight();
- if (cellHeight > 0) {
- int remainder = y % cellHeight;
- if (remainder < 0) {
- y -= (cellHeight + remainder);
- } else {
- y -= remainder;
- }
- }
- int deltaY = y - bounds.y;
- if(deltaY!=0) {
- scrollSmart(0,deltaY);
- setVirtualOrigin(bounds.x, bounds.y += deltaY);
- }
- if (-bounds.y + getRows() * getCellHeight() >= bounds.height) {
- // scrolled to bottom - need to redraw bottom area
- Rectangle clientRect = getClientArea();
- redraw(0, clientRect.height - fCellHeight, clientRect.width, fCellHeight, false);
- }
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
deleted file mode 100644
index 312fcc0..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Anton Leherbauer (Wind River) - [294468] Fix scroller and text line rendering
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-import org.eclipse.swt.graphics.*;
-
-/**
- *
- */
-public interface ILinelRenderer {
- int getCellWidth();
- int getCellHeight();
- void drawLine(ITextCanvasModel model, GC gc, int line, int x, int y, int colFirst, int colLast);
- void onFontChange();
- void setInvertedColors(boolean invert);
- Color getDefaultBackgroundColor();
- void setColors(RGB background, RGB foreground);
- void setFont(Font font);
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModel.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModel.java
deleted file mode 100644
index 75d9ef3..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModel.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
-
-public interface ITextCanvasModel {
- void addCellCanvasModelListener(ITextCanvasModelListener listener);
- void removeCellCanvasModelListener(ITextCanvasModelListener listener);
-
- ITerminalTextDataReadOnly getTerminalText();
- /**
- * This is is
- * @param startLine
- * @param startCol
- * @param height
- * @param width
- */
- void setVisibleRectangle(int startLine, int startCol, int height, int width);
-
- /**
- * @return true when the cursor is shown (used for blinking cursors)
- */
- boolean isCursorOn();
- /**
- * Show/Hide the cursor.
- * @param visible
- */
- void setCursorEnabled(boolean visible);
-
- /**
- * @return true if the cursor is shown.
- */
- boolean isCursorEnabled();
-
- /**
- * @return the line of the cursor
- */
- int getCursorLine();
- /**
- * @return the column of the cursor
- */
- int getCursorColumn();
-
- /**
- * @return the start of the selection or null if nothing is selected
- * {@link Point#x} is the column and {@link Point#y} is the line.
- */
- Point getSelectionStart();
- /**
- * @return the end of the selection or null if nothing is selected
- * {@link Point#x} is the column and {@link Point#y} is the line.
- */
- Point getSelectionEnd();
-
- Point getSelectionAnchor();
-
- void setSelectionAnchor(Point anchor);
- /**
- * Sets the selection. A negative startLine clears the selection.
- * @param startLine
- * @param endLine
- * @param startColumn
- * @param endColumn
- */
- void setSelection(int startLine, int endLine, int startColumn, int endColumn);
-
- /**
- * @param line
- * @return true if line is part of the selection
- */
- boolean hasLineSelection(int line);
-
- String getSelectedText();
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModelListener.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModelListener.java
deleted file mode 100644
index 5a96bc7..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ITextCanvasModelListener.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-/**
- */
-public interface ITextCanvasModelListener {
- void rangeChanged(int col, int line, int width, int height);
- void dimensionsChanged(int cols, int rows);
- /**
- * Called when any text change happened. Used to scroll to the
- * end of text in auto scroll mode. This does not get fired
- * when the window of interest has changed!
- */
- void terminalDataChanged();
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/PipedInputStream.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/PipedInputStream.java
deleted file mode 100644
index f0e1132..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/PipedInputStream.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 1996, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Douglas Lea (Addison Wesley) - [cq:1552] BoundedBufferWithStateTracking adapted to BoundedByteBuffer
- * Martin Oberhuber (Wind River) - the waitForAvailable method
- * Martin Oberhuber (Wind River) - [208166] Avoid unnecessary arraycopy in BoundedByteBuffer
- * Pawel Piech (Wind River) - [333613] "Job found still running" after shutdown
- *******************************************************************************/
-
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * The main purpose of this class is to start a runnable in the
- * display thread when data is available and to pretend no data
- * is available after a given amount of time the runnable is running.
- *
- */
-public class PipedInputStream extends InputStream {
- /**
- * The output stream used by the terminal backend to write to the terminal
- */
- protected final OutputStream fOutputStream;
- /**
- * A blocking byte queue.
- */
- private final BoundedByteBuffer fQueue;
-
- /**
- * A byte bounded buffer used to synchronize the input and the output stream.
- * <p>
- * Adapted from BoundedBufferWithStateTracking
- * http://gee.cs.oswego.edu/dl/cpj/allcode.java
- * http://gee.cs.oswego.edu/dl/cpj/
- * <p>
- * BoundedBufferWithStateTracking is part of the examples for the book
- * Concurrent Programming in Java: Design Principles and Patterns by
- * Doug Lea (ISBN 0-201-31009-0). Second edition published by
- * Addison-Wesley, November 1999. The code is
- * Copyright(c) Douglas Lea 1996, 1999 and released to the public domain
- * and may be used for any purposes whatsoever.
- * <p>
- * For some reasons a solution based on
- * PipedOutputStream/PipedIntputStream
- * does work *very* slowly:
- * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4404700
- * <p>
- *
- */
- private class BoundedByteBuffer {
- protected final byte[] fBuffer; // the elements
- protected int fPutPos = 0; // circular indices
- protected int fTakePos = 0;
- protected int fUsedSlots = 0; // the count
- private boolean fClosed;
- public BoundedByteBuffer(int capacity) throws IllegalArgumentException {
- // make sure we don't deadlock on too small capacity
- if (capacity <= 0)
- throw new IllegalArgumentException();
- fBuffer = new byte[capacity];
- }
- /**
- * @return the bytes available for {@link #read()}
- * Must be called with a lock on this!
- */
- public int available() {
- return fUsedSlots;
- }
- /**
- * Writes a single byte to the buffer. Blocks if the buffer is full.
- * @param b byte to write to the buffer
- * @throws InterruptedException when the thread is interrupted while waiting
- * for the buffer to become ready
- * Must be called with a lock on this!
- */
- public void write(byte b) throws InterruptedException {
- while (fUsedSlots == fBuffer.length)
- // wait until not full
- wait();
-
- fBuffer[fPutPos] = b;
- fPutPos = (fPutPos + 1) % fBuffer.length; // cyclically increment
-
- if (fUsedSlots++ == 0) // signal if was empty
- notifyAll();
- }
- public int getFreeSlots() {
- return fBuffer.length - fUsedSlots;
- }
- public void write(byte[] b, int off, int len) throws InterruptedException {
- assert len<=getFreeSlots();
- while (fUsedSlots == fBuffer.length)
- // wait until not full
- wait();
- int n = Math.min(len, fBuffer.length - fPutPos);
- System.arraycopy(b, off, fBuffer, fPutPos, n);
- if (fPutPos + len > fBuffer.length)
- System.arraycopy(b, off + n, fBuffer, 0, len - n);
- fPutPos = (fPutPos + len) % fBuffer.length; // cyclically increment
- boolean wasEmpty = fUsedSlots == 0;
- fUsedSlots += len;
- if (wasEmpty) // signal if was empty
- notifyAll();
- }
- /**
- * Read a single byte. Blocks until a byte is available.
- * @return a byte from the buffer
- * @throws InterruptedException when the thread is interrupted while waiting
- * for the buffer to become ready
- * Must be called with a lock on this!
- */
- public int read() throws InterruptedException {
- while (fUsedSlots == 0) {
- if(fClosed)
- return -1;
- // wait until not empty
- wait();
- }
- byte b = fBuffer[fTakePos];
- fTakePos = (fTakePos + 1) % fBuffer.length;
-
- if (fUsedSlots-- == fBuffer.length) // signal if was full
- notifyAll();
- return b;
- }
- public int read(byte[] cbuf, int off, int len) throws InterruptedException {
- assert len<=available();
- while (fUsedSlots == 0) {
- if(fClosed)
- return 0;
- // wait until not empty
- wait();
- }
- int n = Math.min(len, fBuffer.length - fTakePos);
- System.arraycopy(fBuffer, fTakePos, cbuf, off, n);
- if (fTakePos + len > n)
- System.arraycopy(fBuffer, 0, cbuf, off + n, len - n);
- fTakePos = (fTakePos + len) % fBuffer.length;
- boolean wasFull = fUsedSlots == fBuffer.length;
- fUsedSlots -= len;
- if(wasFull)
- notifyAll();
-
- return len;
- }
- public void close() {
- fClosed=true;
- notifyAll();
- }
- public boolean isClosed() {
- return fClosed;
- }
- }
-
- /**
- * An output stream that calls {@link PipedInputStream#textAvailable}
- * every time data is written to the stream. The data is written to
- * {@link PipedInputStream#fQueue}.
- *
- */
- class PipedOutputStream extends OutputStream {
- public void write(byte[] b, int off, int len) throws IOException {
- try {
- synchronized (fQueue) {
- if(fQueue.isClosed())
- throw new IOException("Stream is closed!"); //$NON-NLS-1$
- int written=0;
- while(written<len) {
- if(fQueue.getFreeSlots()==0) {
- // if no slots available, write one byte and block
- // until free slots are available
- fQueue.write(b[off + written]);
- written++;
- } else {
- // if slots are available, write as much as
- // we can in one junk
- int n=Math.min(fQueue.getFreeSlots(), len-written);
- fQueue.write(b, off + written, n);
- written+=n;
- }
- }
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- public void write(int b) throws IOException {
- try {
- synchronized(fQueue) {
- if(fQueue.isClosed())
- throw new IOException("Stream is closed!"); //$NON-NLS-1$
- fQueue.write((byte)b);
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- public void close() throws IOException {
- synchronized(fQueue) {
- fQueue.close();
- }
- }
- }
- /**
- * @param bufferSize the size of the buffer of the output stream
- */
- public PipedInputStream(int bufferSize) {
- fOutputStream =new PipedOutputStream();
- fQueue=new BoundedByteBuffer(bufferSize);
- }
- /**
- * @return the output stream used by the backend to write to the terminal.
- */
- public OutputStream getOutputStream() {
- return fOutputStream;
- }
- /**
- * Waits until data is available for reading.
- * @param millis see {@link Object#wait(long)}
- * @throws InterruptedException when the thread is interrupted while waiting
- * for the buffer to become ready
- */
- public void waitForAvailable(long millis) throws InterruptedException {
- synchronized(fQueue) {
- if(fQueue.available()==0 && !fQueue.fClosed)
- fQueue.wait(millis);
- }
- }
- /**
- * Must be called in the Display Thread!
- * @return number of characters available for reading.
- */
- public int available() {
- synchronized(fQueue) {
- return fQueue.available();
- }
- }
- /**
- * @return the next available byte. Check with {@link #available}
- * if characters are available.
- */
- public int read() throws IOException {
- try {
- synchronized (fQueue) {
- return fQueue.read();
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return -1;
- }
- }
- /**
- * Closing a <tt>PipedInputStream</tt> is the same as closing the output stream.
- * The stream will allow reading data that's still in the pipe after which it will
- * throw an <tt>IOException</tt>.
- */
- public void close() throws IOException {
- synchronized(fQueue) {
- fQueue.close();
- }
- }
-
- public int read(byte[] cbuf, int off, int len) throws IOException {
- int n=0;
- if(len==0)
- return 0;
- // read as much as we can using a single synchronized statement
- try {
- synchronized (fQueue) {
- // if nothing available, block and read one byte
- if (fQueue.available() == 0) {
- // block now until at least one byte is available
- int c = fQueue.read();
- // are we at the end of stream
- if (c == -1)
- return -1;
- cbuf[off] = (byte) c;
- n++;
- }
- // is there more data available?
- if (n < len && fQueue.available() > 0) {
- // read at most available()
- int nn = Math.min(fQueue.available(), len - n);
- // are we at the end of the stream?
- if (nn == 0 && fQueue.isClosed()) {
- // if no byte was read, return -1 to indicate end of stream
- // else return the bytes we read up to now
- if (n == 0)
- n = -1;
- return n;
- }
- fQueue.read(cbuf, off + n, nn);
- n += nn;
- }
-
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- return n;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/PollingTextCanvasModel.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/PollingTextCanvasModel.java
deleted file mode 100644
index 9ca0304..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/PollingTextCanvasModel.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
-
-/**
- * @author Michael.Scharf@scharf-software.com
- *
- */
-public class PollingTextCanvasModel extends AbstractTextCanvasModel {
- int fPollInterval=50;
- /**
- *
- */
- public PollingTextCanvasModel(ITerminalTextDataSnapshot snapshot) {
- super(snapshot);
- Display.getDefault().timerExec(fPollInterval,new Runnable(){
- public void run() {
- update();
- Display.getDefault().timerExec(fPollInterval,this);
- }});
- }
- public void setUpdateInterval(int t) {
- fPollInterval=t;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/StyleMap.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/StyleMap.java
deleted file mode 100644
index c91294e..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/StyleMap.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Michael Scharf (Wind River) - [205260] Terminal does not take the font from the preferences
- * Michael Scharf (Wind River) - [209746] There are cases where some colors not displayed correctly
- * Michael Scharf (Wind River) - [206328] Terminal does not draw correctly with proportional fonts
- * Martin Oberhuber (Wind River) - [247700] Terminal uses ugly fonts in JEE package
- * Martin Oberhuber (Wind River) - [335358] Fix Terminal color definition
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-import java.util.*;
-
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.tm.terminal.model.*;
-
-public class StyleMap {
- private static final String BLACK = "black"; //$NON-NLS-1$
- private static final String WHITE = "white"; //$NON-NLS-1$
- private static final String WHITE_FOREGROUND = "white_foreground"; //$NON-NLS-1$
- private static final String GRAY = "gray"; //$NON-NLS-1$
- private static final String MAGENTA = "magenta"; //$NON-NLS-1$
- private static final String CYAN = "cyan"; //$NON-NLS-1$
- private static final String YELLOW = "yellow"; //$NON-NLS-1$
- private static final String BLUE = "blue"; //$NON-NLS-1$
- private static final String GREEN = "green"; //$NON-NLS-1$
- private static final String RED = "red"; //$NON-NLS-1$
-
- private static final String PREFIX = "org.eclipse.tm.internal."; //$NON-NLS-1$
- // TODO propagate the name of the font in the FontRegistry
- private static final String fDefaultFontName="terminal.views.view.font.definition"; //$NON-NLS-1$
- String fFontName=fDefaultFontName;
- Map fColorMapForeground=new HashMap();
- Map fColorMapBackground=new HashMap();
- Map fColorMapIntense=new HashMap();
- Map fFontMap=new HashMap();
- private Point fCharSize;
- private final Style fDefaultStyle;
- private boolean fInvertColors;
- private boolean fProportional;
- private final int[] fOffsets=new int[256];
- private RGB background = new RGB(0, 0, 0);
- private RGB foreground = new RGB(229, 229, 229);
- private Font font = JFaceResources.getFontRegistry().get(fFontName);
- StyleMap() {
- initColors();
- fDefaultStyle=Style.getStyle(StyleColor.getStyleColor(BLACK),StyleColor.getStyleColor(WHITE));
- updateFont();
- }
- private void initColors() {
- initForegroundColors();
- initBackgroundColors();
- initIntenseColors();
- }
- private void initForegroundColors() {
- if(fInvertColors) {
- setColor(fColorMapForeground, WHITE, 0, 0, 0);
- setColor(fColorMapForeground, WHITE_FOREGROUND, 50, 50, 50);
- setColor(fColorMapForeground, BLACK, foreground.red, foreground.green, foreground.blue); // set foreground
- } else {
- setColor(fColorMapForeground, WHITE, 255, 255, 255);
- setColor(fColorMapForeground, WHITE_FOREGROUND, 229, 229, 229);
- setColor(fColorMapForeground, BLACK, 50, 50, 50);
- }
- setColor(fColorMapForeground, RED, 205, 0, 0);
- setColor(fColorMapForeground, GREEN, 0, 205, 0);
- setColor(fColorMapForeground, BLUE, 0, 0, 238);
- setColor(fColorMapForeground, YELLOW, 205, 205, 0);
- setColor(fColorMapForeground, CYAN, 0, 205, 205);
- setColor(fColorMapForeground, MAGENTA, 205, 0, 205);
- setColor(fColorMapForeground, GRAY, 229, 229, 229);
- }
-
- private void initBackgroundColors() {
- if(fInvertColors) {
- setColor(fColorMapBackground, WHITE, background.red, background.green, background.blue); // set background
- setColor(fColorMapBackground, WHITE_FOREGROUND, 50, 50, 50); // only used when colors are inverse
- setColor(fColorMapBackground, BLACK, foreground.red, foreground.green, foreground.blue); // set cursor color
- } else {
- setColor(fColorMapBackground, WHITE, 255, 255, 255);
- setColor(fColorMapBackground, WHITE_FOREGROUND, 229, 229, 229);
- setColor(fColorMapBackground, BLACK, 0, 0, 0);
- }
- setColor(fColorMapBackground, RED, 205, 0, 0);
- setColor(fColorMapBackground, GREEN, 0, 205, 0);
- setColor(fColorMapBackground, BLUE, 0, 0, 238);
- setColor(fColorMapBackground, YELLOW, 205, 205, 0);
- setColor(fColorMapBackground, CYAN, 0, 205, 205);
- setColor(fColorMapBackground, MAGENTA, 205, 0, 205);
- setColor(fColorMapBackground, GRAY, 229, 229, 229);
- }
-
- private void initIntenseColors() {
- if(fInvertColors) {
- setColor(fColorMapIntense, WHITE, 127, 127, 127);
- setColor(fColorMapIntense, WHITE_FOREGROUND, 0, 0, 0); // only used when colors are inverse
- setColor(fColorMapIntense, BLACK, 255, 255, 255);
- } else {
- setColor(fColorMapIntense, WHITE, 255, 255, 255);
- setColor(fColorMapIntense, WHITE_FOREGROUND, 255, 255, 255);
- setColor(fColorMapIntense, BLACK, 0, 0, 0);
- }
- setColor(fColorMapIntense, RED, 255, 0, 0);
- setColor(fColorMapIntense, GREEN, 0, 255, 0);
- setColor(fColorMapIntense, BLUE, 92, 92, 255);
- setColor(fColorMapIntense, YELLOW, 255, 255, 0);
- setColor(fColorMapIntense, CYAN, 0, 255, 255);
- setColor(fColorMapIntense, MAGENTA, 255, 0, 255);
- setColor(fColorMapIntense, GRAY, 255, 255, 255);
- }
-
- private void setColor(Map colorMap, String name, int r, int g, int b) {
- String colorName=PREFIX+r+"-"+g+"-"+b; //$NON-NLS-1$//$NON-NLS-2$
- Color color=JFaceResources.getColorRegistry().get(colorName);
- if(color==null) {
- JFaceResources.getColorRegistry().put(colorName, new RGB(r,g,b));
- color=JFaceResources.getColorRegistry().get(colorName);
- }
- colorMap.put(StyleColor.getStyleColor(name), color);
- colorMap.put(StyleColor.getStyleColor(name.toUpperCase()), color);
- }
-
- public Color getForegrondColor(Style style) {
- style = defaultIfNull(style);
- Map map = style.isBold() ? fColorMapIntense : fColorMapForeground;
- //Map map = fColorMapForeground;
- if(style.isReverse()) {
- return getColor(map ,style.getBackground());
- } else {
- return getColor(map ,style.getForground());
- }
- }
- public Color getBackgroundColor(Style style) {
- style = defaultIfNull(style);
- if(style.isReverse()) {
- return getColor(fColorMapBackground,style.getForground());
- } else {
- return getColor(fColorMapBackground,style.getBackground());
- }
- }
- Color getColor(Map map,StyleColor color) {
- Color c=(Color) map.get(color);
- if(c==null) {
- c=Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
- }
- return c;
- }
- private Style defaultIfNull(Style style) {
- if(style==null) {
- style=fDefaultStyle;
- }
- return style;
- }
- public void setInvertedColors(boolean invert) {
- if(invert==fInvertColors) {
- return;
- }
- fInvertColors=invert;
- initColors();
- }
-// static Font getBoldFont(Font font) {
-// FontData fontDatas[] = font.getFontData();
-// FontData data = fontDatas[0];
-// return new Font(Display.getCurrent(), data.getName(), data.getHeight(), data.getStyle()|SWT.BOLD);
-// }
-
- public Font getFont(Style style) {
- style = defaultIfNull(style);
- FontData fontDatas[] = font.getFontData();
- FontData data = fontDatas[0];
- if(style.isBold()) {
- return new Font(font.getDevice(), data.getName(), data.getHeight(), data.getStyle() | SWT.BOLD);
- } else if(style.isUnderline()) {
- return new Font(font.getDevice(), data.getName(), data.getHeight(), data.getStyle() | SWT.ITALIC);
- }
- return font;
- }
-
- public Font getFont() {
- return font;
-
- }
- public int getFontWidth() {
- return fCharSize.x;
- }
- public int getFontHeight() {
- return fCharSize.y;
- }
- public void updateFont() {
- Display display=Display.getCurrent();
- GC gc = new GC (display);
- if (JFaceResources.getFontRegistry().hasValueFor(fDefaultFontName)) {
- fFontName = fDefaultFontName;
- } else if (JFaceResources.getFontRegistry().hasValueFor("REMOTE_COMMANDS_VIEW_FONT")) { //$NON-NLS-1$
- //try RSE Shell View Font
- fFontName = "REMOTE_COMMANDS_VIEW_FONT"; //$NON-NLS-1$
- } else {
- //fall back to "basic jface text font"
- fFontName = "org.eclipse.jface.textfont"; //$NON-NLS-1$
- }
- gc.setFont(getFont());
- fCharSize = gc.textExtent ("W"); //$NON-NLS-1$
- fProportional=false;
-
- for (char c = ' '; c <= '~'; c++) {
- // consider only the first 128 chars for deciding if a font
- // is proportional
- if(measureChar(gc, c, true)) {
- fProportional=true;
- }
- }
- // TODO should we also consider the upper 128 chars??
- for (char c = ' '+128; c <= '~'+128; c++) {
- measureChar(gc, c,false);
- }
- if(fProportional) {
- fCharSize.x-=2; //works better on small fonts
- }
- for (int i = 0; i < fOffsets.length; i++) {
- fOffsets[i]=(fCharSize.x-fOffsets[i])/2;
- }
- if(!fProportional) {
- //measure font in boldface, too, and if wider then treat like proportional
- gc.setFont(getFont(fDefaultStyle.setBold(true)));
- Point charSizeBold = gc.textExtent("W"); //$NON-NLS-1$
- if (fCharSize.x != charSizeBold.x) {
- fProportional=true;
- }
- }
- gc.dispose ();
- }
- /**
- * @param gc
- * @param c
- * @param updateMax
- * @return true if the the font is proportional
- */
- private boolean measureChar(GC gc, char c, boolean updateMax) {
- boolean proportional=false;
- Point ext=gc.textExtent(String.valueOf(c));
- if(ext.x>0 && ext.y>0 && (fCharSize.x!=ext.x || fCharSize.y!=ext.y)) {
- proportional=true;
- if(updateMax) {
- fCharSize.x=Math.max(fCharSize.x, ext.x);
- fCharSize.y=Math.max(fCharSize.y, ext.y);
- }
- }
- fOffsets[c]=ext.x;
- return proportional;
- }
- public boolean isFontProportional() {
- return fProportional;
- }
- /**
- * Return the offset in pixels required to center a given character
- * @param c the character to measure
- * @return the offset in x direction to center this character
- */
- public int getCharOffset(char c) {
- if(c>=fOffsets.length) {
- return 0;
- }
- return fOffsets[c];
- }
-
- public void setColors(RGB background, RGB foreground) {
- this.background = background;
- this.foreground = foreground;
- initColors();
- }
-
- public void setFont(Font font) {
- this.font = font;
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
deleted file mode 100644
index 7b60217..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Michael Scharf (Wind River) - [240098] The cursor should not blink when the terminal is disconnected
- * Uwe Stieber (Wind River) - [281328] The very first few characters might be missing in the terminal control if opened and connected programmatically
- * Martin Oberhuber (Wind River) - [294327] After logging in, the remote prompt is hidden
- * Anton Leherbauer (Wind River) - [294468] Fix scroller and text line rendering
- * Uwe Stieber (Wind River) - [205486] Fix ScrollLock always moving to line 1
- * Anton Leherbauer (Wind River) - [219589] Copy an entire line selection
- * Anton Leherbauer (Wind River) - [196465] Resizing Terminal changes Scroller location
- * Anton Leherbauer (Wind River) - [324608] Terminal has strange scrolling behaviour
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Composite;
-
-/**
- * A cell oriented Canvas. Maintains a list of "cells".
- * It can either be vertically or horizontally scrolled.
- * The CellRenderer is responsible for painting the cell.
- */
-public class TextCanvas extends GridCanvas {
- protected final ITextCanvasModel fCellCanvasModel;
- /** Renders the cells */
- private final ILinelRenderer fCellRenderer;
- private boolean fScrollLock;
- private Point fDraggingStart;
- private Point fDraggingEnd;
- private boolean fHasSelection;
- private ResizeListener fResizeListener;
-
- // The minSize is meant to determine the minimum size of the backing store
- // (grid) into which remote data is rendered. If the viewport is smaller
- // than that minimum size, the backing store size remains at the minSize,
- // and a scrollbar is shown instead. In reality, this has the following
- // issues or effects today:
- // (a) Bug 281328: For very early data coming in before the widget is
- // realized, the minSize determines into what initial grid that is
- // rendered. See also @link{#addResizeHandler(ResizeListener)}.
- // (b) Bug 294468: Since we have redraw and size computation problems
- // with horizontal scrollers, for now the minColumns must be small
- // enough to avoid a horizontal scroller appearing in most cases.
- // (b) Bug 294327: since we have problems with the vertical scroller
- // showing the correct location, minLines must be small enough
- // to avoid a vertical scroller or new data may be rendered off-screen.
- // As a compromise, we have been working with a 20x4 since the Terminal
- // inception, though many users would want a 80x24 minSize and backing
- // store. Pros and cons of the small minsize:
- // + consistent "remote size==viewport size", vi works as expected
- // - dumb terminals which expect 80x24 render garbled on small viewport.
- // If bug 294468 were resolved, an 80 wide minSize would be preferrable
- // since it allows switching the terminal viewport small/large as needed,
- // without destroying the backing store. For a complete solution,
- // Bug 196462 tracks the request for a user-defined fixed-widow-size-mode.
- private int fMinColumns=80;
- private int fMinLines=4;
- private boolean fCursorEnabled;
- private boolean fResizing;
-
- /**
- * Create a new CellCanvas with the given SWT style bits.
- * (SWT.H_SCROLL and SWT.V_SCROLL are automatically added).
- */
- public TextCanvas(Composite parent, ITextCanvasModel model, int style,ILinelRenderer cellRenderer) {
- super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
- fCellRenderer=cellRenderer;
- setCellWidth(fCellRenderer.getCellWidth());
- setCellHeight(fCellRenderer.getCellHeight());
- fCellCanvasModel=model;
- fCellCanvasModel.addCellCanvasModelListener(new ITextCanvasModelListener(){
- @Override
- public void rangeChanged(int col, int line, int width, int height) {
- repaintRange(col,line,width,height);
- }
- @Override
- public void dimensionsChanged(int cols, int rows) {
- calculateGrid();
- }
- @Override
- public void terminalDataChanged() {
- if(isDisposed()) {
- return;
- }
- // scroll to end (unless scroll lock is active)
- if (!fResizing) {
- calculateGrid();
- scrollToEnd();
- }
- }
- });
- // let the cursor blink if the text canvas gets the focus...
- addFocusListener(new FocusListener(){
- @Override
- public void focusGained(FocusEvent e) {
- fCellCanvasModel.setCursorEnabled(fCursorEnabled);
- }
- @Override
- public void focusLost(FocusEvent e) {
- fCellCanvasModel.setCursorEnabled(false);
- }});
- addMouseListener(new MouseListener(){
- @Override
- public void mouseDoubleClick(MouseEvent e) {
- }
- @Override
- public void mouseDown(MouseEvent e) {
- if(e.button==1) { // left button
- fDraggingStart=screenPointToCell(e.x, e.y);
- fHasSelection=false;
- if((e.stateMask&SWT.SHIFT)!=0) {
- Point anchor=fCellCanvasModel.getSelectionAnchor();
- if(anchor!=null) {
- fDraggingStart=anchor;
- }
- } else {
- fCellCanvasModel.setSelectionAnchor(fDraggingStart);
- }
- fDraggingEnd=null;
- }
- }
- @Override
- public void mouseUp(MouseEvent e) {
- if(e.button==1) { // left button
- updateHasSelection(e);
- if(fHasSelection) {
- setSelection(screenPointToCell(e.x, e.y));
- } else {
- fCellCanvasModel.setSelection(-1,-1,-1,-1);
- }
- fDraggingStart=null;
- }
- }
- });
- addMouseMoveListener(new MouseMoveListener() {
-
- @Override
- public void mouseMove(MouseEvent e) {
- if (fDraggingStart != null) {
- updateHasSelection(e);
- setSelection(screenPointToCell(e.x, e.y));
- }
- }
- });
- serVerticalBarVisible(true);
- setHorizontalBarVisible(false);
- }
-
- /**
- * The user has to drag the mouse to at least one character to make a selection.
- * Once this is done, even a one char selection is OK.
- *
- * @param e
- */
- private void updateHasSelection(MouseEvent e) {
- if(fDraggingStart!=null) {
- Point p=screenPointToCell(e.x, e.y);
- if(fDraggingStart.x!=p.x||fDraggingStart.y!=p.y) {
- fHasSelection=true;
- }
- }
- }
-
- void setSelection(Point p) {
- if (fDraggingStart !=null && !p.equals(fDraggingEnd)) {
- fDraggingEnd = p;
- if (compare(p, fDraggingStart) < 0) {
- // bug 219589 - make sure selection start coordinates are non-negative
- int startColumn = Math.max(0, p.x);
- int startRow = Math.max(p.y, 0);
- fCellCanvasModel.setSelection(startRow, fDraggingStart.y, startColumn, fDraggingStart.x);
- } else {
- fCellCanvasModel.setSelection(fDraggingStart.y, p.y, fDraggingStart.x, p.x);
-
- }
- }
- }
-
- int compare(Point p1, Point p2) {
- if (p1.equals(p2)) {
- return 0;
- }
- if (p1.y == p2.y) {
- if (p1.x > p2.x) {
- return 1;
- } else {
- return -1;
- }
- }
- if (p1.y > p2.y) {
- return 1;
- } else {
- return -1;
- }
- }
- public ILinelRenderer getCellRenderer() {
- return fCellRenderer;
- }
-
- public int getMinColumns() {
- return fMinColumns;
- }
-
- public void setMinColumns(int minColumns) {
- fMinColumns = minColumns;
- }
-
- public int getMinLines() {
- return fMinLines;
- }
-
- public void setMinLines(int minLines) {
- fMinLines = minLines;
- }
-
- protected void onResize(boolean init) {
- if(fResizeListener!=null) {
- Rectangle bonds=getClientArea();
- int cellHeight = getCellHeight();
- int cellWidth = getCellWidth();
- int lines=bonds.height/cellHeight;
- int columns=bonds.width/cellWidth;
- // when the view is minimised, its size is set to 0
- // we don't sent this to the terminal!
- if((lines>0 && columns>0) || init) {
- if(columns<fMinColumns) {
- if(!isHorizontalBarVisble()) {
- setHorizontalBarVisible(true);
- bonds=getClientArea();
- lines=bonds.height/cellHeight;
- }
- columns=fMinColumns;
- } else if(columns>=fMinColumns && isHorizontalBarVisble()) {
- setHorizontalBarVisible(false);
- bonds=getClientArea();
- lines=bonds.height/cellHeight;
- columns=bonds.width/cellWidth;
- }
- if(lines<fMinLines) {
- lines=fMinLines;
- }
- fResizeListener.sizeChanged(lines, columns);
- }
- }
- super.onResize();
- calculateGrid();
- }
-
- @Override
- protected void onResize() {
- fResizing = true;
- try {
- onResize(false);
- } finally {
- fResizing = false;
- }
- }
-
- private void calculateGrid() {
- Rectangle virtualBounds = getVirtualBounds();
- setRedraw(false);
- try {
- setVirtualExtend(getCols()*getCellWidth(),getRows()*getCellHeight());
- getParent().layout();
- if (fResizing) {
- // scroll to end if view port was near last line
- Rectangle viewRect = getViewRectangle();
- if (virtualBounds.height - (viewRect.y + viewRect.height) < getCellHeight() * 2) {
- scrollToEnd();
- }
- }
- } finally {
- setRedraw(true);
- }
- }
- void scrollToEnd() {
- if(!fScrollLock) {
- int y=-(getRows()*getCellHeight()-getClientArea().height);
- if (y > 0) {
- y = 0;
- }
- Rectangle v=getViewRectangle();
- if(v.y!=-y) {
- setVirtualOrigin(v.x,y);
- }
- // make sure the scroll area is correct:
- scrollY(getVerticalBar());
- scrollX(getHorizontalBar());
- }
- }
- /**
- *
- * @return true if the cursor should be shown on output....
- */
- public boolean isScrollLock() {
- return fScrollLock;
- }
- /**
- * If set then if the size changes
- */
- public void setScrollLock(boolean scrollLock) {
- fScrollLock=scrollLock;
- }
- protected void repaintRange(int col, int line, int width, int height) {
- Point origin=cellToOriginOnScreen(col,line);
- Rectangle r=new Rectangle(origin.x,origin.y,width*getCellWidth(),height*getCellHeight());
- repaint(r);
- }
- @Override
- protected void drawLine(GC gc, int line, int x, int y, int colFirst, int colLast) {
- fCellRenderer.drawLine(fCellCanvasModel, gc,line,x,y,colFirst, colLast);
- }
- @Override
- protected Color getTerminalBackgroundColor() {
- return fCellRenderer.getDefaultBackgroundColor();
- }
- @Override
- protected void visibleCellRectangleChanged(int x, int y, int width, int height) {
- fCellCanvasModel.setVisibleRectangle(y,x,height,width);
- update();
- }
- @Override
- protected int getCols() {
- return fCellCanvasModel.getTerminalText().getWidth();
- }
- @Override
- protected int getRows() {
- return fCellCanvasModel.getTerminalText().getHeight();
- }
- public String getSelectionText() {
- // TODO -- create a hasSelectionMethod!
- return fCellCanvasModel.getSelectedText();
- }
- public void copy() {
- Clipboard clipboard = new Clipboard(getDisplay());
- clipboard.setContents(new Object[] { getSelectionText() }, new Transfer[] { TextTransfer.getInstance() });
- clipboard.dispose();
- }
- public void selectAll() {
- fCellCanvasModel.setSelection(0, fCellCanvasModel.getTerminalText().getHeight(), 0, fCellCanvasModel.getTerminalText().getWidth());
- fCellCanvasModel.setSelectionAnchor(new Point(0,0));
- }
- public boolean isEmpty() {
- return false;
- }
- /**
- * Gets notified when the visible size of the terminal changes.
- * This should update the model!
- *
- */
- public interface ResizeListener {
- void sizeChanged(int lines, int columns);
- }
- /**
- * @param listener this listener gets notified, when the size of
- * the widget changed. It should change the dimensions of the underlying
- * terminaldata
- */
- public void addResizeHandler(ResizeListener listener) {
- if(fResizeListener!=null)
- {
- throw new IllegalArgumentException("There can be at most one listener at the moment!"); //$NON-NLS-1$
- }
- fResizeListener=listener;
-
- // Bug 281328: [terminal] The very first few characters might be missing in
- // the terminal control if opened and connected programmatically
- //
- // In case the terminal had not been visible yet or is too small (less than one
- // line visible), the terminal should have a minimum size to avoid RuntimeExceptions.
- Rectangle bonds=getClientArea();
- if (bonds.height<getCellHeight() || bonds.width<getCellWidth()) {
- //Widget not realized yet, or minimized to < 1 item:
- //Just tell the listener our min size
- fResizeListener.sizeChanged(getMinLines(), getMinColumns());
- } else {
- //Widget realized: compute actual size and force telling the listener
- onResize(true);
- }
- }
-
- public void onFontChange() {
- fCellRenderer.onFontChange();
- setCellWidth(fCellRenderer.getCellWidth());
- setCellHeight(fCellRenderer.getCellHeight());
- calculateGrid();
- }
-
- public void setInvertedColors(boolean invert) {
- fCellRenderer.setInvertedColors(invert);
- redraw();
- }
-
- /**
- * @return true if the cursor is enabled (blinking). By default the cursor is not enabled.
- */
- public boolean isCursorEnabled() {
- return fCursorEnabled;
- }
-
- /**
- * @param enabled enabling means that the cursor blinks
- */
- public void setCursorEnabled(boolean enabled) {
- if(enabled!=fCursorEnabled) {
- fCursorEnabled=enabled;
- fCellCanvasModel.setCursorEnabled(fCursorEnabled);
- }
-
- }
-
- public void setColors(RGB background, RGB foreground) {
- fCellRenderer.setColors(background, foreground);
- redraw();
- }
-
- @Override public void setFont(Font font) {
- super.setFont(font);
- fCellRenderer.setFont(font);
- redraw();
- }
-
- @Override public Point screenPointToCell(int x, int y) {
- return super.screenPointToCell(x, y);
- }
-}
-
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
deleted file mode 100644
index d83bbe0..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Michael Scharf (Wind River) - [205260] Terminal does not take the font from the preferences
- * Michael Scharf (Wind River) - [206328] Terminal does not draw correctly with proportional fonts
- * Anton Leherbauer (Wind River) - [294468] Fix scroller and text line rendering
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
-import org.eclipse.tm.terminal.model.LineSegment;
-import org.eclipse.tm.terminal.model.Style;
-
-/**
- *
- */
-public class TextLineRenderer implements ILinelRenderer {
- private final ITextCanvasModel fModel;
- StyleMap fStyleMap=new StyleMap();
- public TextLineRenderer(TextCanvas c, ITextCanvasModel model) {
- fModel=model;
- }
- /* (non-Javadoc)
- * @see com.imagicus.thumbs.view.ICellRenderer#getCellWidth()
- */
- public int getCellWidth() {
- return fStyleMap.getFontWidth();
- }
- /* (non-Javadoc)
- * @see com.imagicus.thumbs.view.ICellRenderer#getCellHeight()
- */
- public int getCellHeight() {
- return fStyleMap.getFontHeight();
- }
- public void drawLine(ITextCanvasModel model, GC gc, int line, int x, int y, int colFirst, int colLast) {
- if(line<0 || line>=getTerminalText().getHeight() || colFirst>=getTerminalText().getWidth() || colFirst-colLast==0) {
- fillBackground(gc, x, y, getCellWidth()*(colLast-colFirst), getCellHeight());
- } else {
- colLast=Math.min(colLast, getTerminalText().getWidth());
- LineSegment[] segments=getTerminalText().getLineSegments(line, colFirst, colLast-colFirst);
- for (int i = 0; i < segments.length; i++) {
- LineSegment segment=segments[i];
- Style style=segment.getStyle();
- setupGC(gc, style);
- String text=segment.getText();
- drawText(gc, x, y, colFirst, segment.getColumn(), text);
- drawCursor(model, gc, line, x, y, colFirst);
- }
- if(fModel.hasLineSelection(line)) {
- gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
- gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION));
- Point start=model.getSelectionStart();
- Point end=model.getSelectionEnd();
- char[] chars=model.getTerminalText().getChars(line);
- if(chars==null)
- return;
- int offset=0;
- if(start.y==line)
- offset=start.x;
- offset=Math.max(offset, colFirst);
- int len;
- if(end.y==line)
- len=end.x-offset+1;
- else
- len=chars.length-offset+1;
- len=Math.min(len,chars.length-offset);
- if(len>0) {
- String text=new String(chars,offset,len);
- drawText(gc, x, y, colFirst, offset, text);
- }
- }
- }
- }
-
- private void fillBackground(GC gc, int x, int y, int width, int height) {
- Color bg=gc.getBackground();
- gc.setBackground(getDefaultBackgroundColor());
- gc.fillRectangle (x,y,width,height);
- gc.setBackground(bg);
-
- }
-
- public Color getDefaultBackgroundColor() {
- // null == default style
- return fStyleMap.getBackgroundColor(null);
- }
-
- private void drawCursor(ITextCanvasModel model, GC gc, int row, int x, int y, int colFirst) {
- if(!model.isCursorOn())
- return;
- int cursorLine=model.getCursorLine();
-
- if(row==cursorLine) {
- int cursorColumn=model.getCursorColumn();
- if(cursorColumn<getTerminalText().getWidth()) {
- Style style=getTerminalText().getStyle(row, cursorColumn);
- if(style==null) {
- // TODO make the cursor color customizable
- style=Style.getStyle("BLACK", "WHITE"); //$NON-NLS-1$//$NON-NLS-2$
- }
- style=style.setReverse(!style.isReverse());
- setupGC(gc,style);
- String text=String.valueOf(getTerminalText().getChar(row, cursorColumn));
- drawText(gc, x, y, colFirst, cursorColumn, text);
- }
- }
- }
- private void drawText(GC gc, int x, int y, int colFirst, int col, String text) {
- int offset=(col-colFirst)*getCellWidth();
- if(fStyleMap.isFontProportional()) {
- // draw the background
- // TODO why does this not work???????
-// gc.fillRectangle(x,y,fStyleMap.getFontWidth()*text.length(),fStyleMap.getFontHeight());
- for (int i = 0; i < text.length(); i++) {
- char c=text.charAt(i);
- int xx=x+offset+i*fStyleMap.getFontWidth();
- // TODO why do I have to draw the background character by character??????
- gc.fillRectangle(xx,y,fStyleMap.getFontWidth(),fStyleMap.getFontHeight());
- if(c!=' ' && c!='\000') {
- gc.drawString(String.valueOf(c),fStyleMap.getCharOffset(c)+xx,y,true);
- }
- }
- } else {
- text=text.replace('\000', ' ');
- gc.drawString(text,x+offset,y,false);
- }
- }
- private void setupGC(GC gc, Style style) {
- Color c=fStyleMap.getForegrondColor(style);
- if(c!=gc.getForeground()) {
- gc.setForeground(c);
- }
- c=fStyleMap.getBackgroundColor(style);
- if(c!=gc.getBackground()) {
- gc.setBackground(c);
- }
- Font f=fStyleMap.getFont(style);
- if(f!=gc.getFont()) {
- gc.setFont(f);
- }
- }
- ITerminalTextDataReadOnly getTerminalText() {
- return fModel.getTerminalText();
- }
- public void onFontChange() {
- fStyleMap.updateFont();
- }
- public void setInvertedColors(boolean invert) {
- fStyleMap.setInvertedColors(invert);
-
- }
-
- @Override public void setColors(RGB background, RGB foreground) {
- fStyleMap.setColors(background, foreground);
- }
-
- @Override public void setFont(Font font) {
- fStyleMap.setFont(font);
- }
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/VirtualCanvas.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/VirtualCanvas.java
deleted file mode 100644
index 42ced4a..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/VirtualCanvas.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Anton Leherbauer (Wind River) - [294468] Fix scroller and text line rendering
- *******************************************************************************/
-package org.eclipse.tm.internal.terminal.textcanvas;
-
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Canvas;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.ScrollBar;
-import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
-
-/**
- * A <code>Canvas</code> showing a virtual object.
- * Virtual: the extent of the total canvas.
- * Screen: the visible client area in the screen.
- */
-public abstract class VirtualCanvas extends Canvas {
-
- private final Rectangle fVirtualBounds = new Rectangle(0,0,0,0);
- private Rectangle fClientArea;
- /**
- * prevent infinite loop in {@link #updateScrollbars()}
- */
- private boolean fInUpdateScrollbars;
- private static boolean fInUpdateScrollbarsLogged;
-
- public VirtualCanvas(Composite parent, int style) {
- super(parent, style|SWT.NO_BACKGROUND|SWT.NO_REDRAW_RESIZE);
- fClientArea=getClientArea();
- addListener(SWT.Paint, new Listener() {
- public void handleEvent(Event event) {
- paint(event.gc);
- }
- });
- addListener(SWT.Resize, new Listener() {
- public void handleEvent(Event event) {
- fClientArea=getClientArea();
- onResize();
- }
- });
- getVerticalBar().addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event e) {
- scrollY((ScrollBar)e.widget);
-
- }
-
- });
- getHorizontalBar().addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event e) {
- scrollX((ScrollBar)e.widget);
-
- }
- });
- }
- protected void onResize() {
- updateViewRectangle();
- }
- protected void scrollX(ScrollBar hBar) {
- int hSelection = hBar.getSelection ();
- int destX = -hSelection - fVirtualBounds.x;
- fVirtualBounds.x = -hSelection;
- scrollSmart(destX, 0);
- updateViewRectangle();
- }
- protected void scrollXDelta(int delta) {
- getHorizontalBar().setSelection(-fVirtualBounds.x+delta);
- scrollX(getHorizontalBar());
- }
-
- protected void scrollY(ScrollBar vBar) {
- int vSelection = vBar.getSelection ();
- int destY = -vSelection - fVirtualBounds.y;
- if(destY!=0) {
- fVirtualBounds.y = -vSelection;
- scrollSmart(0,destY);
- updateViewRectangle();
- }
-
- }
- protected void scrollYDelta(int delta) {
- getVerticalBar().setSelection(-fVirtualBounds.y+delta);
- scrollY(getVerticalBar());
- }
-
-
- protected void scrollSmart(int deltaX, int deltaY) {
- if (deltaX != 0 || deltaY != 0) {
- Rectangle rect = getBounds();
- scroll (deltaX, deltaY, 0, 0, rect.width, rect.height, false);
- }
- }
-
- /**
- * @param rect in virtual space
- */
- protected void revealRect(Rectangle rect) {
- Rectangle visibleRect=getScreenRectInVirtualSpace();
- // scroll the X part
- int deltaX=0;
- if(rect.x<visibleRect.x) {
- deltaX=rect.x-visibleRect.x;
- } else if(visibleRect.x+visibleRect.width<rect.x+rect.width){
- deltaX=(rect.x+rect.width)-(visibleRect.x+visibleRect.width);
- }
- if(deltaX!=0) {
- getHorizontalBar().setSelection(-fVirtualBounds.x+deltaX);
- scrollX(getHorizontalBar());
- }
-
- // scroll the Y part
- int deltaY=0;
- if(rect.y<visibleRect.y){
- deltaY=rect.y-visibleRect.y;
- } else if(visibleRect.y+visibleRect.height<rect.y+rect.height){
- deltaY=(rect.y+rect.height)-(visibleRect.y+visibleRect.height);
-
- }
- if(deltaY!=0) {
- getVerticalBar().setSelection(-fVirtualBounds.y+deltaY);
- scrollY(getVerticalBar());
- }
- }
-
- protected void repaint(Rectangle r) {
- if(isDisposed())
- return;
- if(inClipping(r,fClientArea)) {
- redraw(r.x, r.y, r.width, r.height, true);
- update();
- }
- }
-
- /**
- * Paint the virtual canvas.
- * Override to implement actual paint method.
- * @param gc graphics context to paint in
- */
- abstract protected void paint(GC gc);
- protected Color getTerminalBackgroundColor() {
-// return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
- return getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
- }
- protected void paintUnoccupiedSpace(GC gc, Rectangle clipping) {
- int width=fVirtualBounds.width + fVirtualBounds.x;
- int height=fVirtualBounds.height + fVirtualBounds.y;
- int marginWidth = (clipping.x+clipping.width) - width;
- int marginHeight = (clipping.y+clipping.height) - height;
- if(marginWidth>0||marginHeight>0){
- Color bg=getBackground();
- gc.setBackground(getTerminalBackgroundColor());
- if (marginWidth > 0) {
- gc.fillRectangle (width, clipping.y, marginWidth, clipping.height);
- }
- if (marginHeight > 0) {
- gc.fillRectangle (clipping.x, height, clipping.width, marginHeight);
- }
- gc.setBackground(bg);
- }
- }
- /**
- * @private
- */
- protected boolean inClipping(Rectangle clipping, Rectangle r) {
- // TODO check if this is OK in all cases (the <=!)
- //
- if(r.x+r.width<=clipping.x)
- return false;
- if(clipping.x+clipping.width<=r.x)
- return false;
- if(r.y+r.height<=clipping.y)
- return false;
- if(clipping.y+clipping.height<=r.y)
- return false;
-
- return true;
- }
- /**
- * @return the screen rect in virtual space (starting with (0,0))
- * of the visible screen. (x,y>=0)
- */
- protected Rectangle getScreenRectInVirtualSpace() {
- Rectangle r= new Rectangle(fClientArea.x-fVirtualBounds.x,fClientArea.y-fVirtualBounds.y,fClientArea.width,fClientArea.height);
- return r;
- }
- /**
- * @return the rect in virtual space (starting with (0,0))
- * of the visible screen. (x,y>=0)
- */
- protected Rectangle getRectInVirtualSpace(Rectangle r) {
- return new Rectangle(r.x-fVirtualBounds.x,r.y-fVirtualBounds.y,r.width,r.height);
- }
-
- /**
- * Sets the extent of the virtual display area
- * @param width width of the display area
- * @param height height of the display area
- */
- protected void setVirtualExtend(int width, int height) {
- fVirtualBounds.width=width;
- fVirtualBounds.height=height;
- updateScrollbars();
- updateViewRectangle();
- }
- /**
- * sets the scrolling origin. Also sets the scrollbars.
- * Does NOT redraw!
- * Use negative values (move the virtual origin to the top left
- * to see something in the screen (which is located at (0,0))
- * @param x
- * @param y
- */
- protected void setVirtualOrigin(int x, int y) {
- if (fVirtualBounds.x != x || fVirtualBounds.y != y) {
- fVirtualBounds.x=x;
- fVirtualBounds.y=y;
- getHorizontalBar().setSelection(-x);
- getVerticalBar().setSelection(-y);
- updateViewRectangle();
- }
- }
- protected Rectangle getVirtualBounds() {
- return cloneRectangle(fVirtualBounds);
- }
- /**
- * @param x
- * @return the virtual coordinate in screen space
- */
- protected int virtualXtoScreen(int x) {
- return x+fVirtualBounds.x;
- }
- protected int virtualYtoScreen(int y) {
- return y+fVirtualBounds.y;
- }
- protected int screenXtoVirtual(int x) {
- return x-fVirtualBounds.x;
- }
- protected int screenYtoVirtual(int y) {
- return y-fVirtualBounds.y;
- }
- /** called when the viewed part is changing */
- private final Rectangle fViewRectangle=new Rectangle(0,0,0,0);
- protected void updateViewRectangle() {
- if(
- fViewRectangle.x==-fVirtualBounds.x
- && fViewRectangle.y==-fVirtualBounds.y
- && fViewRectangle.width==fClientArea.width
- && fViewRectangle.height==fClientArea.height
- )
- return;
- fViewRectangle.x=-fVirtualBounds.x;
- fViewRectangle.y=-fVirtualBounds.y;
- fViewRectangle.width=fClientArea.width;
- fViewRectangle.height=fClientArea.height;
- viewRectangleChanged(fViewRectangle.x,fViewRectangle.y,fViewRectangle.width,fViewRectangle.height);
- }
- protected Rectangle getViewRectangle() {
- return cloneRectangle(fViewRectangle);
- }
- private Rectangle cloneRectangle(Rectangle r) {
- return new Rectangle(r.x,r.y,r.width,r.height);
- }
- /**
- * Called when the viewed part has changed.
- * Override when you need this information....
- * Is only called if the values change!
- * @param x visible in virtual space
- * @param y visible in virtual space
- * @param width
- * @param height
- */
- protected void viewRectangleChanged(int x, int y, int width, int height) {
- }
- /**
- * @private
- */
- private void updateScrollbars() {
- // don't get into infinite loops....
- if(!fInUpdateScrollbars) {
- fInUpdateScrollbars=true;
- try {
- doUpdateScrollbar();
- } finally {
- fInUpdateScrollbars=false;
- }
- } else {
- if(!fInUpdateScrollbarsLogged) {
- fInUpdateScrollbarsLogged=true;
- TerminalPlugin.getDefault().getLog().log(new Status(IStatus.WARNING,
- TerminalPlugin.PLUGIN_ID, IStatus.OK, "Unexpected Recursion in terminal", //$NON-NLS-1$
- new RuntimeException()));
- }
- }
- }
- private void doUpdateScrollbar() {
- Rectangle clientArea= getClientArea();
- ScrollBar horizontal= getHorizontalBar();
- // even if setVisible was called on the scrollbar, isVisible
- // returns false if its parent is not visible.
- if(!isVisible() || horizontal.isVisible()) {
- horizontal.setPageIncrement(clientArea.width - horizontal.getIncrement());
- int max= fVirtualBounds.width;
- horizontal.setMaximum(max);
- horizontal.setThumb(clientArea.width);
- }
- ScrollBar vertical= getVerticalBar();
- // even if setVisible was called on the scrollbar, isVisible
- // returns false if its parent is not visible.
- if(!isVisible() || vertical.isVisible()) {
- vertical.setPageIncrement(clientArea.height - vertical.getIncrement());
- int max= fVirtualBounds.height;
- vertical.setMaximum(max);
- vertical.setThumb(clientArea.height);
- }
- }
- protected boolean isVertialBarVisible() {
- return getVerticalBar().isVisible();
- }
- protected void serVerticalBarVisible(boolean showVScrollBar) {
- ScrollBar vertical= getVerticalBar();
- vertical.setVisible(showVScrollBar);
- vertical.setSelection(0);
- }
- protected boolean isHorizontalBarVisble() {
- return getHorizontalBar().isVisible();
- }
- protected void setHorizontalBarVisible(boolean showHScrollBar) {
- ScrollBar horizontal= getHorizontalBar();
- horizontal.setVisible(showHScrollBar);
- horizontal.setSelection(0);
- }
-}
-
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextData.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextData.java
deleted file mode 100644
index 3ca1815..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextData.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-/**
- * A writable matrix of characters and {@link Style}. This is intended to be the
- * low level representation of the text of a Terminal. Higher layers are
- * responsible to fill the text and styles into this representation.
- * <p>
- * <b>Note: </b> Implementations of this interface has to be thread safe.
- * </p>
- *
- * @noimplement This interface is not intended to be implemented by clients.
- * @noextend This interface is not intended to be extended by clients.
- */
-public interface ITerminalTextData extends ITerminalTextDataReadOnly {
-
- /**
- * Sets the dimensions of the data. If the dimensions are smaller than the current
- * dimensions, the lines will be chopped. If the dimensions are bigger, then
- * the new elements will be filled with 0 chars and null Style.
- * @param height
- * @param width
- */
- void setDimensions(int height, int width);
-
- void setMaxHeight(int height);
- int getMaxHeight();
-
- /**
- * Set a single character and the associated {@link Style}.
- * @param line line must be >=0 and < height
- * @param column column must be >=0 and < width
- * @param c the new character at this position
- * @param style the style or null
- */
- void setChar(int line, int column, char c, Style style);
-
- /**
- * Set an array of characters showing in the same {@link Style}.
- * @param line line must be >=0 and < height
- * @param column column must be >=0 and < width
- * @param chars the new characters at this position
- * @param style the style or null
- */
- void setChars(int line, int column, char[] chars, Style style);
-
- /**
- * Set a subrange of an array of characters showing in the same {@link Style}.
- * @param line line must be >=0 and < height
- * @param column column must be >=0 and < width
- * @param chars the new characters at this position
- * @param start the start index in the chars array
- * @param len the number of characters to insert. Characters beyond width are not inserted.
- * @param style the style or null
- */
- void setChars(int line, int column, char[] chars, int start, int len, Style style);
-
-
- /**
- * Cleans the entire line.
- * @param line
- */
- void cleanLine(int line);
- // /**
- // * @param line
- // * @return true if this line belongs to the previous line but is simply
- // * wrapped.
- // */
- // boolean isWrappedLine(int line);
- //
- // /**
- // * Makes this line an extension to the previous line. Wrapped lines get folded back
- // * when the width of the terminal changes
- // * @param line
- // * @param extendsPreviousLine
- // */
- // void setWrappedLine(int line, boolean extendsPreviousLine);
-
- /**
- * Shifts some lines up or down. The "empty" space is filled with <code>'\000'</code> chars
- * and <code>null</code> {@link Style}
- * <p>To illustrate shift, here is some sample data:
- * <pre>
- * 0 aaaa
- * 1 bbbb
- * 2 cccc
- * 3 dddd
- * 4 eeee
- * </pre>
- *
- * Shift a region of 3 lines <b>up</b> by one line <code>shift(1,3,-1)</code>
- * <pre>
- * 0 aaaa
- * 1 cccc
- * 2 dddd
- * 3
- * 4 eeee
- * </pre>
- *
- *
- * Shift a region of 3 lines <b>down</b> by one line <code>shift(1,3,1)</code>
- * <pre>
- * 0 aaaa
- * 1
- * 2 bbbb
- * 3 cccc
- * 4 eeee
- * </pre>
- * @param startLine the start line of the shift
- * @param size the number of lines to shift
- * @param shift how much scrolling is done. New scrolled area is filled with <code>'\000</code>'.
- * Negative number means scroll down, positive scroll up (see example above).
- */
- void scroll(int startLine, int size, int shift);
-
- /**Adds a new line to the terminal. If maxHeigth is reached, the entire terminal
- * will be scrolled. Else a line will be added.
- */
- void addLine();
- /**
- * Copies the entire source into this and changes the size accordingly
- * @param source
- */
- void copy(ITerminalTextData source);
- /**
- * Copy a sourceLine from source to this at destLine.
- * @param source
- * @param sourceLine
- * @param destLine
- */
- void copyLine(ITerminalTextData source,int sourceLine, int destLine);
- /**
- * Copy <code>length</code> lines from source starting at sourceLine into this starting at
- * destLine.
- * @param source
- * @param sourceStartLine
- * @param destStartLine
- * @param length
- */
- void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine,int length);
-
- void setCursorLine(int line);
- void setCursorColumn(int column);
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextDataReadOnly.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextDataReadOnly.java
deleted file mode 100644
index 0503b4c..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextDataReadOnly.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-/**
- * @noimplement This interface is not intended to be implemented by clients.
- * @noextend This interface is not intended to be extended by clients.
- */
-public interface ITerminalTextDataReadOnly {
-
- /**
- * @return the width of the terminal
- */
- int getWidth();
-
- /**
- * @return the height of the terminal
- */
- int getHeight();
-
- /**
- * @param line be >=0 and < height
- * @param startCol must be >=0 and < width
- * @param numberOfCols must be > 0
- * @return a the line segments of the specified range
- */
- LineSegment[] getLineSegments(int line, int startCol, int numberOfCols);
-
- /**
- * @param line must be >=0 and < height
- * @param column must be >=0 and < width
- * @return the character at column,line
- */
- char getChar(int line, int column);
-
- /**
- * @param line must be >=0 and < height
- * @param column must be >=0 and < width
- * @return style at column,line or null
- */
- Style getStyle(int line, int column);
-
- /**
- * Creates a new instance of {@link ITerminalTextDataSnapshot} that
- * can be used to track changes. Make sure to call {@link ITerminalTextDataSnapshot#detach()}
- * if you don't need the snapshots anymore.
- * <p><b>Note: </b>A new snapshot is empty and needs a call to {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)} to
- * get its initial values. You might want to setup the snapshot to your needs by calling
- * {@link ITerminalTextDataSnapshot#setInterestWindow(int, int)}.
- * </p>
- * @return a new instance of {@link ITerminalTextDataSnapshot} that "listens" to changes of
- * <code>this</code>.
- */
- public ITerminalTextDataSnapshot makeSnapshot();
-
- char[] getChars(int line);
- Style[] getStyles(int line);
-
- /**
- * @return the line in which the cursor is at the moment
- */
- int getCursorLine();
- /**
- * @return the column at which the cursor is at the moment
- */
- int getCursorColumn();
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextDataSnapshot.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextDataSnapshot.java
deleted file mode 100644
index 198f5ed..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/ITerminalTextDataSnapshot.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-/**
- * This class maintains a snapshot of an instance of {@link ITerminalTextData}.
- * While the {@link ITerminalTextData} continues changing, the snapshot remains
- * unchanged until the next snapshot is taken by calling
- * {@link #updateSnapshot(boolean)}. This is important, because the
- * {@link ITerminalTextData} might get modified by another thread. Suppose you
- * would want to draw the content of the {@link ITerminalTextData} using the
- * following loop:
- *
- * <pre>
- * for (int line = 0; line < term.getHeight(); line++)
- * for (int column = 0; column < term.getWidth(); column++)
- * drawCharacter(column, line, term.getChar(column, line), term.getStyle(column, line));
- * </pre>
- *
- * This might fail because the background thread could change the dimensions of
- * the {@link ITerminalTextData} while you iterate the loop. One solution would
- * be to put a <code>synchronized(term){}</code> statement around the code. This
- * has two problems: 1. you would have to know about the internals of the
- * synchronisation of {@link ITerminalTextData}. 2. The other thread that
- * changes {@link ITerminalTextData} is blocked while the potentially slow
- * drawing is done.
- * <p>
- * <b>Solution:</b> Take a snapshot of the terminal and use the snapshot to draw
- * the content. There is no danger that the data structure get changed while you
- * draw. There are also methods to find out what has changed to minimize the
- * number of lines that get redrawn.
- * </p>
- *
- * <p>
- * <b>Drawing optimization</b>: To optimize redrawing of changed lines, this
- * class keeps track of lines that have changed since the previous snapshot.
- * </p>
- *
- * <pre>
- * // iterate over the potentially changed lines
- * for (int line = snap.getFirstChangedLine(); line <= snap.getLastChangedLine(); line++)
- * // redraw only if the line has changed
- * if (snap.hasLineChanged(line))
- * for (int column = 0; column < snap.getWidth(); column++)
- * drawCharacter(column, line, snap.getChar(column, line), snap.getStyle(column, line));
- * </pre>
- *
- * <p>
- * <b>Scroll optimization:</b> Often new lines are appended at the bottom of the
- * terminal and the rest of the lines are scrolled up. In this case all lines
- * would be marked as changed. To optimize for this case,
- * {@link #updateSnapshot(boolean)} can be called with <code>true</code> for the
- * <code>detectScrolling</code> parameter. The object will keep track of
- * scrolling. The UI must <b>first</b> handle the scrolling and then use the
- * {@link #hasLineChanged(int)} method to determine scrolling:
- *
- * <pre>
- * // scroll the visible region of the UI <b>before</b> drawing the changed lines.
- * doUIScrolling(snap.getScrollChangeY(), snap.getScrollChangeN(), snap.getScrollChangeShift());
- * // iterate over the potentially changed lines
- * for (int line = snap.getFirstChangedLine(); line <= snap.getFirstChangedLine(); line++)
- * // redraw only if the line has changed
- * if (snap.hasLineChanged(line))
- * for (int column = 0; column < snap.getWidth(); column++)
- * drawCharacter(column, line, snap.getChar(column, line), snap.getStyle(column, line));
- * </pre>
- *
- * </p>
- * <p>
- * <b>Threading Note</b>: This class is not thread safe! All methods have to be
- * called by the a same thread, that created the instance by calling
- * {@link ITerminalTextDataReadOnly#makeSnapshot()}.
- * </p>
- *
- * @noimplement This interface is not intended to be implemented by clients.
- * @noextend This interface is not intended to be extended by clients.
- */
-public interface ITerminalTextDataSnapshot extends ITerminalTextDataReadOnly {
- /**
- * This listener gets called when the current snapshot
- * is out of date. Calling {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)}
- * will have an effect. Once the {@link #snapshotOutOfDate(ITerminalTextDataSnapshot)} method is called,
- * it will not be called until {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)}
- * is called and a new snapshot needs to be updated again.
- * <p>
- * A typical terminal view would not update the snapshot immediately
- * after the {@link #snapshotOutOfDate(ITerminalTextDataSnapshot)} has been called. It would introduce a
- * delay to update the UI (and the snapshot} 10 or 20 times per second.
- *
- * <p>Make sure you don't spend too much time in this method.
- */
- interface SnapshotOutOfDateListener {
- /**
- * Gets called when the snapshot is out of date. To get the snapshot up to date,
- * call {@link ITerminalTextDataSnapshot#updateSnapshot(boolean)}.
- * @param snapshot The snapshot that is out of date
- */
- void snapshotOutOfDate(ITerminalTextDataSnapshot snapshot);
- }
- void addListener(SnapshotOutOfDateListener listener);
- void removeListener(SnapshotOutOfDateListener listener);
-
- /**
- * Ends the listening to the {@link ITerminalTextData}. After this
- * has been called no new snapshot data is collected.
- */
- void detach();
- /**
- * @return true if the data has changed since the previous snapshot.
- */
- boolean isOutOfDate();
-
- /**
- * The window of interest is the region the snapshot should track.
- * Changes outside this region are ignored. The change takes effect after
- * an update!
- * @param startLine -1 means track the end of the data
- * @param size number of lines to track. A size of -1 means track all.
- */
- void setInterestWindow(int startLine, int size);
- int getInterestWindowStartLine();
- int getInterestWindowSize();
-
- /**
- * Create a new snapshot of the {@link ITerminalTextData}. It will efficiently
- * copy the data of the {@link ITerminalTextData} into an internal representation.
- * The snapshot also keeps track of the changes since the previous snapshot.
- * <p>With the methods {@link #getFirstChangedLine()}, {@link #getLastChangedLine()} and
- * {@link #hasLineChanged(int)}
- * you can find out what has changed in the current snapshot since the previous snapshot.
- * @param detectScrolling if <code>true</code> the snapshot tries to identify scroll
- * changes since the last snapshot. In this case the information about scrolling
- * can be retrieved using the following methods:
- * {@link #getScrollWindowStartLine()}, {@link #getScrollWindowSize()} and {@link #getScrollWindowShift()}
- * <br><b>Note:</b> The method {@link #hasLineChanged(int)} returns changes <b>after</b> the
- * scrolling has been applied.
- */
- void updateSnapshot(boolean detectScrolling);
-
- /**
- * @return The first line changed in this snapshot compared
- * to the previous snapshot.
- *
- * <p><b>Note:</b> If no line has changed, this
- * returns {@link Integer#MAX_VALUE}
- *
- * <p><b>Note:</b> if {@link #updateSnapshot(boolean)} has been called with <code>true</code>,
- * then this does not include lines that only have been scrolled. This is the
- * first line that has changed <b>after</b> the scroll has been applied.
- */
- int getFirstChangedLine();
-
- /**
- * @return The last line changed in this snapshot compared
- * to the previous snapshot. If the height has changed since the
- * last update of the snapshot, then the returned value is within
- * the new dimensions.
- *
- * <p><b>Note:</b> If no line has changed, this returns <code>-1</code>
- *
- * <p><b>Note:</b> if {@link #updateSnapshot(boolean)} has been called with <code>true</code>,
- * then this does not include lines that only have been scrolled. This is the
- * last line that has changed <b>after</b> the scroll has been applied.
- *
- * <p>A typical for loop using this method would look like this (note the <code><=</code> in the for loop):
- * <pre>
- * for(int line=snap.{@link #getFirstChangedLine()}; line <b><=</b> snap.getLastChangedLine(); line++)
- * if(snap.{@link #hasLineChanged(int) hasLineChanged(line)})
- * doSomething(line);
- * </pre>
- */
- int getLastChangedLine();
-
- /**
- * @param line
- * @return true if the line has changed since the previous snapshot
- */
- boolean hasLineChanged(int line);
-
- boolean hasDimensionsChanged();
-
- /**
- * @return true if the terminal has changed (and not just the
- * window of interest)
- */
- boolean hasTerminalChanged();
- /**
- * If {@link #updateSnapshot(boolean)} was called with <code>true</code>, then this method
- * returns the top of the scroll region.
- * @return The first line scrolled in this snapshot compared
- * to the previous snapshot. See also {@link ITerminalTextData#scroll(int, int, int)}.
- */
- int getScrollWindowStartLine();
-
- /**
- * If {@link #updateSnapshot(boolean)} was called with <code>true</code>, then this method
- * returns the size of the scroll region.
- * @return The number of lines scrolled in this snapshot compared
- * to the previous snapshot. See also {@link ITerminalTextData#scroll(int, int, int)}
- * If nothing has changed, 0 is returned.
- */
- int getScrollWindowSize();
-
- /**
- * If {@link #updateSnapshot(boolean)} was called with <code>true</code>, then this method
- * returns number of lines moved by the scroll region.
- * @return The the scroll shift of this snapshot compared
- * to the previous snapshot. See also {@link ITerminalTextData#scroll(int, int, int)}
- */
- int getScrollWindowShift();
-
- /**
- * @return The {@link ITerminalTextData} on that this instance is observing.
- */
- ITerminalTextData getTerminalTextData();
-
-}
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/LineSegment.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/LineSegment.java
deleted file mode 100644
index 9c8c389..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/LineSegment.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-
-public class LineSegment {
- private final String fText;
- private final int fCol;
- private final Style fStyle;
- public LineSegment(int col, String text, Style style) {
- fCol = col;
- fText = text;
- fStyle = style;
- }
- public Style getStyle() {
- return fStyle;
- }
- public String getText() {
- return fText;
- }
- public int getColumn() {
- return fCol;
- }
- public String toString() {
- return "LineSegment("+fCol+", \""+fText+"\","+fStyle+")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- }
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/Style.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/Style.java
deleted file mode 100644
index 9e75514..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/Style.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author scharf
- * Flyweight
- * Threadsafe.
- *
- */
-// TODO add an Object for user data, use weak map to keep track of styles with associated
-// user data
-public class Style {
- private final StyleColor fForground;
- private final StyleColor fBackground;
- private final boolean fBold;
- private final boolean fBlink;
- private final boolean fUnderline;
- private final boolean fReverse;
- private final static Map fgStyles=new HashMap();
- private Style(StyleColor forground, StyleColor background, boolean bold, boolean blink, boolean underline, boolean reverse) {
- fForground = forground;
- fBackground = background;
- fBold = bold;
- fBlink = blink;
- fUnderline = underline;
- fReverse = reverse;
- }
- public static Style getStyle(StyleColor forground, StyleColor background, boolean bold, boolean blink, boolean underline, boolean reverse) {
- Style style = new Style(forground,background, bold, blink,underline,reverse);
- Style cached;
- synchronized (fgStyles) {
- cached=(Style) fgStyles.get(style);
- if(cached==null) {
- cached=style;
- fgStyles.put(cached, cached);
- }
- }
- return cached;
- }
- public static Style getStyle(String forground, String background) {
- return getStyle(StyleColor.getStyleColor(forground), StyleColor.getStyleColor(background),false,false,false,false);
- }
- public static Style getStyle(StyleColor forground, StyleColor background) {
- return getStyle(forground, background,false,false,false,false);
- }
- public Style setForground(StyleColor forground) {
- return getStyle(forground,fBackground,fBold,fBlink,fUnderline,fReverse);
- }
- public Style setBackground(StyleColor background) {
- return getStyle(fForground,background,fBold,fBlink,fUnderline,fReverse);
- }
- public Style setForground(String colorName) {
- return getStyle(StyleColor.getStyleColor(colorName),fBackground,fBold,fBlink,fUnderline,fReverse);
- }
- public Style setBackground(String colorName) {
- return getStyle(fForground,StyleColor.getStyleColor(colorName),fBold,fBlink,fUnderline,fReverse);
- }
- public Style setBold(boolean bold) {
- return getStyle(fForground,fBackground,bold,fBlink,fUnderline,fReverse);
- }
- public Style setBlink(boolean blink) {
- return getStyle(fForground,fBackground,fBold,blink,fUnderline,fReverse);
- }
- public Style setUnderline(boolean underline) {
- return getStyle(fForground,fBackground,fBold,fBlink,underline,fReverse);
- }
- public Style setReverse(boolean reverse) {
- return getStyle(fForground,fBackground,fBold,fBlink,fUnderline,reverse);
- }
- public StyleColor getBackground() {
- return fBackground;
- }
- public boolean isBlink() {
- return fBlink;
- }
- public boolean isBold() {
- return fBold;
- }
- public StyleColor getForground() {
- return fForground;
- }
- public boolean isReverse() {
- return fReverse;
- }
- public boolean isUnderline() {
- return fUnderline;
- }
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((fBackground == null) ? 0 : fBackground.hashCode());
- result = prime * result + (fBlink ? 1231 : 1237);
- result = prime * result + (fBold ? 1231 : 1237);
- result = prime * result + ((fForground == null) ? 0 : fForground.hashCode());
- result = prime * result + (fReverse ? 1231 : 1237);
- result = prime * result + (fUnderline ? 1231 : 1237);
- return result;
- }
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- final Style other = (Style) obj;
- // background == is the same as equals
- if (fBackground != other.fBackground)
- return false;
- if (fBlink != other.fBlink)
- return false;
- if (fBold != other.fBold)
- return false;
- if (fForground != other.fForground)
- return false;
- if (fReverse != other.fReverse)
- return false;
- if (fUnderline != other.fUnderline)
- return false;
- return true;
- }
- public String toString() {
- StringBuffer result=new StringBuffer();
- result.append("Style(foreground="); //$NON-NLS-1$
- result.append(fForground);
- result.append(", background="); //$NON-NLS-1$
- result.append(fBackground);
- if(fBlink)
- result.append(", blink"); //$NON-NLS-1$
- if(fBold)
- result.append(", bold"); //$NON-NLS-1$
- if(fBlink)
- result.append(", blink"); //$NON-NLS-1$
- if(fReverse)
- result.append(", reverse"); //$NON-NLS-1$
- if(fUnderline)
- result.append(", underline"); //$NON-NLS-1$
- result.append(")"); //$NON-NLS-1$
- return result.toString();
- }
-
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/StyleColor.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/StyleColor.java
deleted file mode 100644
index 39dbb66..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/StyleColor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- *
- * Flyweight
- * Threadsafe.
- */
-public class StyleColor {
- private final static Map fgStyleColors=new HashMap();
- final String fName;
-
- /**
- * @param name the name of the color. It is up to the UI to associate a
- * named color with a visual representation
- * @return a StyleColor
- */
- public static StyleColor getStyleColor(String name) {
- StyleColor result;
- synchronized (fgStyleColors) {
- result=(StyleColor) fgStyleColors.get(name);
- if(result==null) {
- result=new StyleColor(name);
- fgStyleColors.put(name, result);
- }
- }
- return result;
- }
- // nobody except the factory method is allowed to instantiate this class!
- private StyleColor(String name) {
- fName = name;
- }
-
- public String getName() {
- return fName;
- }
-
- public String toString() {
- return fName;
- }
- // no need to override equals and hashCode, because Object uses object identity
-}
\ No newline at end of file
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/TerminalTextDataFactory.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/TerminalTextDataFactory.java
deleted file mode 100644
index bb7545d..0000000
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/terminal/model/TerminalTextDataFactory.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Michael Scharf (Wind River) - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tm.terminal.model;
-
-import org.eclipse.tm.internal.terminal.model.SynchronizedTerminalTextData;
-import org.eclipse.tm.internal.terminal.model.TerminalTextData;
-
-public class TerminalTextDataFactory {
- static public ITerminalTextData makeTerminalTextData() {
- return new SynchronizedTerminalTextData(new TerminalTextData());
- }
-}