diff --git a/trunk/system-apps/Terminal/GNUmakefile b/trunk/system-apps/Terminal/GNUmakefile
index 93bb3c6f..d0a4d77a 100644
--- a/trunk/system-apps/Terminal/GNUmakefile
+++ b/trunk/system-apps/Terminal/GNUmakefile
@@ -57,7 +57,9 @@ Terminal_OBJC_FILES = \
 	PreferencesWindowController.m \
 	autokeyviewchain.m \
 	\
-	Label.m
+	Label.m \
+	\
+	RenamingTextField.m
 
 
 
diff --git a/trunk/system-apps/Terminal/RenamingTextField.h b/trunk/system-apps/Terminal/RenamingTextField.h
new file mode 100644
index 00000000..2f1d2b6a
--- /dev/null
+++ b/trunk/system-apps/Terminal/RenamingTextField.h
@@ -0,0 +1,47 @@
+/*
+   Project: GAP, Terminal
+
+   Copyright (C) 2024 Free Software Foundation
+
+   Author: Sergei Golovin <svgdev@mail.ru>
+
+   Created: 2024-02-09 09:56:07 +0400 by dev
+
+   This application is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This application is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+*/
+
+#ifndef _RENAMING_H_
+#define _RENAMING_H_
+
+#import <AppKit/NSTextField.h>
+#import <AppKit/NSEvent.h>
+
+#define RENAME_FIELD_TAG 111
+
+@interface RenamingTextField : NSTextField
+{
+  NSString *_previous;
+  BOOL _escape;
+}
+
+- (void) dealloc;
+- (BOOL) performKeyEquivalent: (NSEvent*)theEvent;
+- (void) setStringValue: (NSString *)aString;
+- (NSString *) stringValue;
+
+@end
+
+#endif // _RENAMING_H_
+
diff --git a/trunk/system-apps/Terminal/RenamingTextField.m b/trunk/system-apps/Terminal/RenamingTextField.m
new file mode 100644
index 00000000..6398f05e
--- /dev/null
+++ b/trunk/system-apps/Terminal/RenamingTextField.m
@@ -0,0 +1,78 @@
+/*
+   Project: GAP, Terminal
+
+   Copyright (C) 2024 Free Software Foundation
+
+   Author: Sergei Golovin <svgdev@mail.ru>
+
+   Created: 2024-02-09 09:56:07 +0400 by dev
+
+   This application is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This application is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+*/
+
+#import "RenamingTextField.h"
+
+@implementation RenamingTextField
+
+- (void) dealloc
+{
+  DESTROY(_previous);
+  [super dealloc];
+}
+
+- (BOOL) performKeyEquivalent: (NSEvent*)theEvent
+{
+  if ([self tag] == RENAME_FIELD_TAG)
+    {
+      NSString *s = [theEvent charactersIgnoringModifiers];
+      unichar ch = [s characterAtIndex: 0];
+
+      if (ch == '\e')
+	{
+	  _escape = YES;
+	  [[self superview] removeSubview: self]; // that would post NSControlTextDidEndEditingNotification
+	  return YES;
+	}
+    }
+
+  return [super performKeyEquivalent: theEvent];
+}
+
+- (void) setStringValue: (NSString *)aString
+{
+  NSString *current = [self stringValue];
+  if ([current length] == 0)
+    {
+      // at initialization
+      ASSIGN(_previous, aString);
+    }
+  else
+    {
+      ASSIGN(_previous, current);
+    }
+  [super setStringValue: aString];
+}
+
+- (NSString *) stringValue
+{
+  if (_escape)
+    {
+      return _previous;
+    }
+
+  return [super stringValue];
+}
+
+@end
diff --git a/trunk/system-apps/Terminal/TerminalWindow.h b/trunk/system-apps/Terminal/TerminalWindow.h
index 92c13ef5..c62a3a85 100644
--- a/trunk/system-apps/Terminal/TerminalWindow.h
+++ b/trunk/system-apps/Terminal/TerminalWindow.h
@@ -16,10 +16,11 @@
 
 #import <AppKit/NSWindowController.h>
 #import <AppKit/NSTabView.h>
+#import <AppKit/NSTextField.h>
 
 extern NSString *TerminalWindowNoMoreActiveWindowsNotification;
 
-@interface TerminalWindowController : NSWindowController
+@interface TerminalWindowController : NSWindowController <NSTextFieldDelegate>
 {
 	NSMutableArray *terminal_views;
 	NSTabView *tab_view;
@@ -51,6 +52,11 @@ extern NSString *TerminalWindowNoMoreActiveWindowsNotification;
 -(void) moveTabLeft;
 -(void) moveTabRight;
 
+-(void) renameTab: (id)sender;
+/* NSText delegate */
+- (void) controlTextDidEndEditing: (NSNotification *)aNotification;
+/* end of NSText delegate */
+
 @end
 
 #endif
diff --git a/trunk/system-apps/Terminal/TerminalWindow.m b/trunk/system-apps/Terminal/TerminalWindow.m
index 83a3fdee..5bdecdf0 100644
--- a/trunk/system-apps/Terminal/TerminalWindow.m
+++ b/trunk/system-apps/Terminal/TerminalWindow.m
@@ -21,13 +21,36 @@
 #import <AppKit/NSScroller.h>
 #import <AppKit/NSTabViewItem.h>
 #import <AppKit/NSWindow.h>
+#import <AppKit/NSImage.h>
+#import <AppKit/NSEvent.h>
 #import <GNUstepGUI/GSHbox.h>
+#import <GNUstepGUI/GSTheme.h>
 
 #import "TerminalWindow.h"
 
 #import "TerminalWindowPrefs.h"
 #import "TerminalView.h"
+#import "RenamingTextField.h"
 
+#define RENAME_FIELD_WIDTH 150
+
+@interface      GSTheme ( Terminal )
+/* Returns the current height of any tab of the supplied type */
+- (CGFloat) tabHeightForType: (NSTabViewType)type;
+@end
+
+@implementation GSTheme ( Terminal )
+- (CGFloat) tabHeightForType: (NSTabViewType)type
+{
+  NSImage *img = [self imageForTabPart: GSTabUnSelectedLeft type: type];
+  if (img == nil)
+    {
+      return 0;
+    }
+  return [img size].height;
+}
+
+@end
 
 /* TODO: this needs cleaning up. chances are this will interfere
 with NSTask */
@@ -124,6 +147,7 @@ NSString *TerminalWindowNoMoreActiveWindowsNotification=
 	[scroller release];
 
 	tab_view = [[NSTabView alloc] init];
+	//[tab_view setTabViewType: NSBottomTabsBezelBorder]; // to test bottom placed tabs
 	[tab_view setDelegate:self];
 	tab_item = [[NSTabViewItem alloc] init];
 	[tab_item setLabel:@"Terminal"];
@@ -159,6 +183,8 @@ NSString *TerminalWindowNoMoreActiveWindowsNotification=
           }
 	DESTROY(hb);
 
+	// to make tab renaming workable initially with one tab
+	[tab_view selectLastTabViewItem: nil];
 
 	[win release];
 
@@ -589,5 +615,176 @@ static NSMutableArray *idle_list;
 	[tv setNeedsDisplay:YES];
 }
 
-@end
+- (NSSize) _sizeOfTabViewItem: (NSTabViewItem *)item
+{
+    /* the code here is based on GSThemeDrawing.m, -drawTabViewRect:inView:withItems:selectedItem: */
+  GSTheme *theme = [GSTheme theme];
+  NSTabView *tabView = [item tabView];
+  NSTabViewType type = [tabView tabViewType];
+  BOOL truncate = [tabView allowsTruncatedLabels];
+  NSImage *part = nil;
+  NSTabState itemState = [item tabState];
+  NSTabState previousState;
+  NSSize size = [item sizeOfLabel: truncate];
+  NSInteger idx = [tabView indexOfTabViewItem: item];
+  NSUInteger width = size.width;
+  NSSize itemSize = NSMakeSize(size.width, size.height);
+
+  // the left image
+  if (idx == 0)
+    {
+      if (itemState == NSSelectedTab)
+	{
+	  part = [theme imageForTabPart: GSTabSelectedLeft type: type];
+	}
+      else if (itemState == NSBackgroundTab)
+	{
+	  part = [theme imageForTabPart: GSTabUnSelectedLeft type: type];
+	}
+      else
+	NSLog(@"Not finished yet. Luff ya.\n");
+
+      width += [part size].width;
+    }
+  else
+    {
+      if (itemState == NSSelectedTab)
+	{
+	  part = [theme imageForTabPart: GSTabUnSelectedToSelectedJunction type: type];
+	}
+      else if (itemState == NSBackgroundTab)
+	{
+	  previousState = [[tabView tabViewItemAtIndex: idx - 1] tabState];
+	  if (previousState == NSSelectedTab)
+	    {
+	      part = [theme imageForTabPart: GSTabSelectedToUnSelectedJunction type: type];
+	    }
+	  else
+	    {
+	      part = [theme imageForTabPart: GSTabUnSelectedJunction type: type];
+	    }
+	}
+      else
+	NSLog(@"Not finished yet. Luff ya.\n");
+
+      width += [part size].width;
+    }
+
+  itemSize.width = width;
+
+  return itemSize;
+}
+
+- (NSUInteger) _computeOffset
+{
+  /* the code here is based on GSThemeDrawing.m, -drawTabViewRect:inView:withItems:selectedItem: */
+  GSTheme *theme = [GSTheme theme];
+  NSTabViewItem *item = [tab_view selectedTabViewItem];
+  NSTabViewType type = [tab_view tabViewType];
+  NSArray *items = [tab_view tabViewItems];
+  //NSUInteger howMany = [items count];
+  NSEnumerator *en = [items objectEnumerator];
+  NSTabViewItem *titem;
+  NSInteger offset = 0;
+  NSRect bounds = [tab_view bounds];
+  NSRect aRect = [theme tabViewBackgroundRectForBounds: bounds tabViewType: type];
+  NSInteger width = [tab_view  contentRect].size.width;
+  NSInteger iwidth;
+
+  if (type == NSBottomTabsBezelBorder
+      || type == NSTopTabsBezelBorder)
+    {
+      if (type == NSTopTabsBezelBorder)
+	offset = bounds.origin.x;
+      else
+	offset = aRect.origin.x;
+
+      while((titem = [en nextObject]) != nil)
+	{
+	  iwidth = [self _sizeOfTabViewItem: titem ].width;
+
+	  if (item == titem)
+	   {
+	     if (offset + iwidth/2 - RENAME_FIELD_WIDTH/2 > 0)
+	       offset += iwidth/2 - RENAME_FIELD_WIDTH/2;
+	     else
+	       offset = 3*iwidth/8;
+	     if (offset + RENAME_FIELD_WIDTH > width)
+	       offset = width - RENAME_FIELD_WIDTH;
+	     break;
+	   }
+	 offset += iwidth;
+	} // while
+    }
 
+  return offset;
+}
+
+-(void) renameTab: (id)sender
+{
+  if (isShowingTabs)
+    {
+	NSTabViewItem *item = [tab_view selectedTabViewItem];
+	NSUInteger tfheight;
+	NSTextField *tf = [[RenamingTextField alloc] init];
+	NSUInteger offset = [self _computeOffset];
+	NSUInteger type = [tab_view tabViewType];
+
+	[tf setTag: RENAME_FIELD_TAG];
+
+	[tf setDelegate: self];
+	[tf setBezeled: NO];
+	[tf setBordered: YES];
+	[tf setStringValue: [item label]];
+	[tf setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin];
+	[tf sizeToFit];
+	tfheight = [tf frame].size.height;
+
+	[tab_view addSubview: tf];
+
+	if (type == NSTopTabsBezelBorder)
+	  {
+	    [tf setFrameOrigin: NSMakePoint(offset, tfheight)];
+	  }
+	else if (type == NSBottomTabsBezelBorder)
+	  {
+	    [tf setFrameOrigin: NSMakePoint(offset, [[item view] frame].size.height - tfheight)];
+	  }
+	[tf setFrameSize: NSMakeSize(RENAME_FIELD_WIDTH, tfheight)];
+
+	[[self window] makeFirstResponder: tf];
+	[tab_view setNeedsDisplay: YES];
+
+	RELEASE(tf);
+    }
+}
+
+/* NSText delegate */
+- (void) controlTextDidEndEditing: (NSNotification *) aNotification
+{
+  NSTextField *field = (NSTextField *)[aNotification object];
+
+  if([field tag] == RENAME_FIELD_TAG)
+    {
+      NSTabViewItem *item = [tab_view selectedTabViewItem];
+      NSTextField *tf = field;
+      NSString *newLabel = [tf stringValue];
+      NSUInteger idx = [tab_view indexOfTabViewItem: item];
+      TerminalView *tv = [terminal_views objectAtIndex: idx];
+
+      [tv ts_setTitle: newLabel type: 2];
+      [item setLabel: newLabel];
+
+      RETAIN(tf);
+
+      [tab_view removeSubview: tf];
+
+      [[self window] makeFirstResponder: tv];
+      [tab_view setNeedsDisplay: YES];
+
+      AUTORELEASE(tf);
+    }
+}
+/* end of NSText delegate */
+
+@end
diff --git a/trunk/system-apps/Terminal/main.m b/trunk/system-apps/Terminal/main.m
index 573e2620..c0a5a978 100644
--- a/trunk/system-apps/Terminal/main.m
+++ b/trunk/system-apps/Terminal/main.m
@@ -171,6 +171,9 @@
 	[m addItemWithTitle: _(@"New tab")
 		action: @selector(openTab:)
 		keyEquivalent: @"t"];
+	[m addItemWithTitle: _(@"Rename tab")
+		action: @selector(renameTab:)
+	        keyEquivalent: @"R"];
         [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Shell")]];
 	[m release];
 
@@ -261,6 +264,12 @@
 	[[twc frontTerminalView] runShell];
 }
 
+- (void)renameTab: (id)sender
+{
+	TerminalWindowController *twc = [[NSApp keyWindow] windowController];
+	[twc renameTab:sender];
+}
+
 -(void) closeTab: (id)sender
 {
 	TerminalWindowController *twc = [[NSApp keyWindow] windowController];
@@ -587,4 +596,3 @@ int main(int argc, char **argv)
 	DESTROY(arp);
 	return 0;
 }
-
