scrolling groups, take 2
Bert Wesarg
wesarg at informatik.uni-halle.de
Thu Jul 5 17:16:42 CEST 2007
Hello,
here is a small update patch.
Changes:
* fix none working menu entries
* dim the "Detach" menu entry, if the current pane is not in a group
Regards
Bert
-------------- next part --------------
diff -ur nedit.orig/doc/help.etx nedit.syncscroll/doc/help.etx
--- nedit.orig/doc/help.etx 2007-07-02 18:26:15.663198719 +0200
+++ nedit.syncscroll/doc/help.etx 2007-07-03 22:25:01.514574712 +0200
@@ -2464,6 +2464,9 @@
**$show_line_numbers**
Whether line numbers are shown next to the text.
+**$scroll_group**
+ True if this text pane is in an syncronized scroll group;
+
**$show_matching**
Contains the current preference for showing matching pairs,
such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
@@ -3254,6 +3257,13 @@
A value of 0 turns it off and a value of 1 turns it on.
If no parameters are supplied the option is toggled.
+**set_scroll_group( [window_name] [, paneIndex] )**
+ Include this window to the same sync scroll group as window_name and
+ possibly remove this window from the previously group.
+ If no window_name is given or window_name is the empty string remove
+ this window from any group. If paneIndex is not given or paneIndex == -1
+ use the last focused pane from the window, else a valid pane index.
+
**set_show_line_numbers( [0 | 1] )**
Show or hide line numbers for the current window.
A value of 0 turns it off and a value of 1 turns it on.
diff -ur nedit.orig/source/highlightData.c nedit.syncscroll/source/highlightData.c
--- nedit.orig/source/highlightData.c 2007-07-02 18:26:16.497269298 +0200
+++ nedit.syncscroll/source/highlightData.c 2007-07-03 22:26:03.701987020 +0200
@@ -550,10 +550,10 @@
README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
Comment:\"#\":\"$\"::Comment::\n\
Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line)>\":::Identifier::\n\
- Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
+ Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|scroll_group|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
Built-in Special Vars:\"(?<!\\Y)\\$(?:[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
Built-in Subrs:\"<(?:append_file|beep|calltip|clipboard_to_string|dialog|focus_window|get_character|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|kill_calltip|length|list_dialog|max|min|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_language_mode|set_locked|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)>\":::Subroutine::\n\
- Menu Actions:\"<(?:new|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-window|split_window|close-pane|close_pane|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
+ Menu Actions:\"<(?:new|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-window|split_window|close-pane|close_pane|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_scroll_group|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
Text Actions:\"<(?:self-insert|self_insert|grab-focus|grab_focus|extend-adjust|extend_adjust|extend-start|extend_start|extend-end|extend_end|secondary-adjust|secondary_adjust|secondary-or-drag-adjust|secondary_or_drag_adjust|secondary-start|secondary_start|secondary-or-drag-start|secondary_or_drag_start|process-bdrag|process_bdrag|move-destination|move_destination|move-to|move_to|move-to-or-end-drag|move_to_or_end_drag|end_drag|copy-to|copy_to|copy-to-or-end-drag|copy_to_or_end_drag|exchange|process-cancel|process_cancel|paste-clipboard|paste_clipboard|copy-clipboard|copy_clipboard|cut-clipboard|cut_clipboard|copy-primary|copy_primary|cut-primary|cut_primary|newline|newline-and-indent|newline_and_indent|newline-no-indent|newline_no_indent|delete-selection|delete_selection|delete-previous-character|delete_previous_character|delete-next-character|delete_next_character|delete-previous-word|delete_previous_word|delete-next-word|delete_next_word|delete-to-start-of-line|delete_to_start_of_line|delete-to-end-of-line|delete_to_end_of_line|forward-character|forward_character|backward-character|backward_character|key-select|key_select|process-up|process_up|process-down|process_down|process-shift-up|process_shift_up|process-shift-down|process_shift_down|process-home|process_home|forward-word|forward_word|backward-word|backward_word|forward-paragraph|forward_paragraph|backward-paragraph|backward_paragraph|beginning-of-line|beginning_of_line|end-of-line|end_of_line|beginning-of-file|beginning_of_file|end-of-file|end_of_file|next-page|next_page|previous-page|previous_page|page-left|page_left|page-right|page_right|toggle-overstrike|toggle_overstrike|scroll-up|scroll_up|scroll-down|scroll_down|scroll_left|scroll_right|scroll-to-line|scroll_to_line|select-all|select_all|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)>\":::Subroutine::\n\
Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|while)>\":::Keyword::\n\
Braces:\"[{}\\[\\]]\":::Keyword::\n\
diff -ur nedit.orig/source/macro.c nedit.syncscroll/source/macro.c
--- nedit.orig/source/macro.c 2007-07-02 18:26:16.529272006 +0200
+++ nedit.syncscroll/source/macro.c 2007-07-03 22:31:32.708538832 +0200
@@ -297,6 +297,8 @@
DataValue *result, char **errMsg);
static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
DataValue *result, char **errMsg);
+static int scrollGroupMV(WindowInfo *window, DataValue *argList, int nArgs,
+ DataValue *result, char **errMsg);
static int readOnlyMV(WindowInfo *window, DataValue *argList, int nArgs,
DataValue *result, char **errMsg);
static int lockedMV(WindowInfo *window, DataValue *argList, int nArgs,
@@ -449,7 +451,7 @@
statisticsLineMV, incSearchLineMV, showLineNumbersMV,
autoIndentMV, wrapTextMV, highlightSyntaxMV,
makeBackupCopyMV, incBackupMV, showMatchingMV,
- overTypeModeMV, readOnlyMV, lockedMV, fileFormatMV,
+ overTypeModeMV, scrollGroupMV, readOnlyMV, lockedMV, fileFormatMV,
fontNameMV, fontNameItalicMV,
fontNameBoldMV, fontNameBoldItalicMV, subscriptSepMV,
minFontWidthMV, maxFontWidthMV, topLineMV, numDisplayLinesMV,
@@ -467,7 +469,7 @@
"$statistics_line", "$incremental_search_line", "$show_line_numbers",
"$auto_indent", "$wrap_text", "$highlight_syntax",
"$make_backup_copy", "$incremental_backup", "$show_matching",
- "$overtype_mode", "$read_only", "$locked", "$file_format",
+ "$overtype_mode", "$scroll_group", "$read_only", "$locked", "$file_format",
"$font_name", "$font_name_italic",
"$font_name_bold", "$font_name_bold_italic", "$sub_sep",
"$min_font_width", "$max_font_width", "$top_line", "$n_display_lines",
@@ -4298,6 +4300,15 @@
return True;
}
+static int scrollGroupMV(WindowInfo *window, DataValue *argList, int nArgs,
+ DataValue *result, char **errMsg)
+{
+ result->tag = INT_TAG;
+ result->val.n = !TextScrollGroupIsSingle((TextWidget)window->lastFocus);
+
+ return True;
+}
+
static int readOnlyMV(WindowInfo *window, DataValue *argList, int nArgs,
DataValue *result, char **errMsg)
{
diff -ur nedit.orig/source/menu.c nedit.syncscroll/source/menu.c
--- nedit.orig/source/menu.c 2007-07-02 18:26:16.812295955 +0200
+++ nedit.syncscroll/source/menu.c 2007-07-05 17:04:57.780806217 +0200
@@ -311,6 +311,12 @@
Cardinal *nArgs);
static void moveDocumentDialogAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs);
+static void scrollGroupDetachAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs);
+static void scrollGroupDetachDialogAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs);
+static void scrollGroupDialogAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs);
static void nextDocumentAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs);
static void prevDocumentAP(Widget w, XEvent *event, String *args,
@@ -407,6 +413,8 @@
Cardinal *nArgs);
static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs);
+static void setScrollGroupAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs);
static void setLockedAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs);
static void setUseTabsAP(Widget w, XEvent *event, String *args,
@@ -527,6 +535,9 @@
{"detach_document", detachDocumentAP},
{"detach_document_dialog", detachDocumentDialogAP},
{"move_document_dialog", moveDocumentDialogAP},
+ {"scroll_group_detach", scrollGroupDetachAP},
+ {"scroll_group_detach_dialog", scrollGroupDetachDialogAP},
+ {"scroll_group_dialog", scrollGroupDialogAP},
{"next_document", nextDocumentAP},
{"previous_document", prevDocumentAP},
{"last_document", lastDocumentAP},
@@ -577,6 +588,7 @@
{"set_show_matching", setShowMatchingAP},
{"set_match_syntax_based", setMatchSyntaxBasedAP},
{"set_overtype_mode", setOvertypeModeAP},
+ {"set_scroll_group", setScrollGroupAP},
{"set_locked", setLockedAP},
{"set_tab_dist", setTabDistAP},
{"set_em_tab_dist", setEmTabDistAP},
@@ -1222,6 +1234,15 @@
window->moveDocumentItem = createMenuItem(menuPane, "moveDocument",
"Move Tab To...", 'M', doActionCB, "move_document_dialog", SHORT);
XtSetSensitive(window->moveDocumentItem, False);
+
+ btn = createMenuSeparator(menuPane, "sep02", SHORT);
+ XtVaSetValues(btn, XmNuserData, PERMANENT_MENU_ITEM, NULL);
+ window->scrollGroupDetachItem = createMenuItem(menuPane, "scrollGroupDetach",
+ "Detach from Scroll Group", 'S', doActionCB, "scroll_group_detach", SHORT);
+ XtSetSensitive(window->scrollGroupDetachItem, False);
+ window->scrollGroupItem = createMenuItem(menuPane, "scrollGroupDialog",
+ "Join Document To Scroll Group...", 'G', doActionCB, "scroll_group_dialog", SHORT);
+
btn = createMenuSeparator(menuPane, "sep1", SHORT);
XtVaSetValues(btn, XmNuserData, PERMANENT_MENU_ITEM, NULL);
@@ -3531,6 +3552,41 @@
MoveDocumentDialog(WidgetToWindow(w));
}
+static void scrollGroupDetachDialogAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs)
+{
+ WindowInfo *window = WidgetToWindow(w);
+ TextWidget text = (TextWidget)window->lastFocus;
+ int resp;
+
+ if (TextScrollGroupIsSingle(text))
+ return;
+
+ resp = DialogF(DF_QUES, window->shell, 2, "Detach %s from Scroll Group?",
+ "Detach", "Cancel", window->filename);
+
+ if (resp == 1)
+ TextScrollGroupDetach(text);
+}
+
+static void scrollGroupDetachAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs)
+{
+ WindowInfo *window = WidgetToWindow(w);
+ TextWidget text = (TextWidget)window->lastFocus;
+
+ if (TextScrollGroupIsSingle(text))
+ return;
+
+ TextScrollGroupDetach(text);
+}
+
+static void scrollGroupDialogAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs)
+{
+ ScrollGroupDialog(WidgetToWindow(w), -1);
+}
+
static void nextDocumentAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs)
{
@@ -4182,6 +4238,85 @@
SetOverstrike(window, newState);
}
+static void setScrollGroupAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs)
+{
+ WindowInfo *window = WidgetToWindow(w);
+ WindowInfo *win;
+ TextWidget text, targetText = NULL;
+
+ if (*nArgs > 2) {
+ fprintf(stderr, "NEdit: set_scroll_group too many arguments\n");
+ return;
+ }
+
+ text = (TextWidget)window->lastFocus;
+
+ TextScrollGroupDetach(text);
+
+ win = NULL;
+ if (*nArgs == 0 || !strcmp(args[0], "")) {
+ return;
+ }
+ else if (!strcmp(args[0], "last")) {
+ win = WindowList;
+ }
+ else if (!strcmp(args[0], "next")) {
+ win = window->next;
+ }
+ else if (strlen(args[0]) >= MAXPATHLEN) {
+ fprintf(stderr, "NEdit: Pathname too long in set_scroll_group()\n");
+ return;
+ }
+ else {
+ char fullname[MAXPATHLEN];
+ char normalizedString[MAXPATHLEN];
+ /* just use the plain name as supplied */
+ for (win = WindowList; win != NULL; win = win->next) {
+ sprintf(fullname, "%s%s", win->path, win->filename);
+ if (!strcmp(args[0], fullname)) {
+ break;
+ }
+ }
+ /* didn't work? try normalizing the string passed in */
+ if (win == NULL) {
+ strncpy(normalizedString, args[0], MAXPATHLEN);
+ normalizedString[MAXPATHLEN-1] = '\0';
+ if (1 == NormalizePathname(normalizedString)) {
+ /* Something is broken with the input pathname. */
+ fprintf(stderr, "NEdit: Pathname broken in set_scroll_group()\n");
+ return;
+ }
+ for (win = WindowList; win != NULL; win = win->next) {
+ sprintf(fullname, "%s%s", win->path, win->filename);
+ if (!strcmp(normalizedString, fullname))
+ break;
+ }
+ }
+ }
+
+ if (!win)
+ return;
+
+ targetText = NULL;
+ if (*nArgs > 1) {
+ int paneIndex = atoi(args[1]);
+ if (paneIndex >= 0) {
+ targetText = (TextWidget)GetPaneByIndex(win, paneIndex);
+ if (NULL == targetText) {
+ fprintf(stderr, "NEdit: set_scroll_group wrong argument for 2nd parameter\n");
+ return;
+ }
+ }
+ }
+ if (NULL == targetText) {
+ targetText = (TextWidget)win->lastFocus;
+ }
+
+ if (text != targetText)
+ TextScrollGroupJoinWith(text, targetText);
+}
+
static void setLockedAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs)
{
diff -ur nedit.orig/source/nedit.h nedit.syncscroll/source/nedit.h
--- nedit.orig/source/nedit.h 2007-07-02 18:26:16.618279538 +0200
+++ nedit.syncscroll/source/nedit.h 2007-07-03 22:09:34.528709431 +0200
@@ -443,6 +443,8 @@
Widget moveDocumentItem;
Widget contextMoveDocumentItem;
Widget contextDetachDocumentItem;
+ Widget scrollGroupDetachItem;
+ Widget scrollGroupItem;
Widget bgMenuUndoItem;
Widget bgMenuRedoItem;
#ifdef SGI_CUSTOM
diff -ur nedit.orig/source/text.c nedit.syncscroll/source/text.c
--- nedit.orig/source/text.c 2007-07-02 18:26:16.302252796 +0200
+++ nedit.syncscroll/source/text.c 2007-07-03 22:33:54.153727988 +0200
@@ -80,6 +80,10 @@
/* Length of delay in milliseconds for vertical autoscrolling */
#define VERTICAL_SCROLL_DELAY 50
+typedef void (textActionProcCall)(Widget, XEvent*, String*, Cardinal*);
+
+static void syncScrollAP(textActionProcCall actionProc, Widget w,
+ XEvent *event, String *args, Cardinal *nArgs);
static void initialize(TextWidget request, TextWidget new);
static void handleHidePointer(Widget w, XtPointer unused,
XEvent *event, Boolean *continue_to_dispatch);
@@ -877,6 +881,9 @@
XtAddEventHandler((Widget)new, NEDIT_HIDE_CURSOR_MASK, False,
handleHidePointer, (Opaque)NULL);
}
+
+ new->nextScrollGroup = new;
+ new->prevScrollGroup = new;
}
/* Hide the pointer while the user is typing */
@@ -953,6 +960,8 @@
XtRemoveAllCallbacks((Widget)w, textNdragStartCallback);
XtRemoveAllCallbacks((Widget)w, textNdragEndCallback);
+ TextScrollGroupDetach(w);
+
#ifndef NO_XMIM
/* Unregister the widget from the input manager */
XmImUnregister((Widget)w);
@@ -2910,7 +2919,7 @@
}
}
-static void nextPageAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
+static void _nextPageAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
{
textDisp *textD = ((TextWidget)w)->text.textD;
textBuffer *buf = textD->buffer;
@@ -3007,7 +3016,12 @@
}
}
-static void previousPageAP(Widget w, XEvent *event, String *args,
+static void nextPageAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
+{
+ _nextPageAP(w, event, args, nArgs);
+}
+
+static void _previousPageAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs)
{
textDisp *textD = ((TextWidget)w)->text.textD;
@@ -3092,6 +3106,12 @@
}
}
+static void previousPageAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
+{
+ _previousPageAP(w, event, args, nArgs);
+
+}
+
static void pageLeftAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
{
textDisp *textD = ((TextWidget)w)->text.textD;
@@ -3183,7 +3203,25 @@
}
}
-static void scrollUpAP(Widget w, XEvent *event, String *args,
+/*
+** do synchronous scroll for this action.
+*/
+static void syncScrollAP(textActionProcCall actionProc, Widget w,
+ XEvent *event, String *args, Cardinal *nArgs)
+{
+ TextWidget text = (TextWidget)w;
+ TextWidget t;
+
+ actionProc(w, event, args, nArgs);
+
+ if (text == text->nextScrollGroup)
+ return;
+
+ for (t = text->nextScrollGroup; t != text; t = t->nextScrollGroup)
+ actionProc((Widget)t, event, args, nArgs);
+}
+
+static void _scrollUpAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs)
{
textDisp *textD = ((TextWidget)w)->text.textD;
@@ -3204,7 +3242,13 @@
TextDSetScroll(textD, topLineNum-nLines, horizOffset);
}
-static void scrollDownAP(Widget w, XEvent *event, String *args,
+static void scrollUpAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs)
+{
+ syncScrollAP(_scrollUpAP, w, event, args, nArgs);
+}
+
+static void _scrollDownAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs)
{
textDisp *textD = ((TextWidget)w)->text.textD;
@@ -3225,6 +3269,12 @@
TextDSetScroll(textD, topLineNum+nLines, horizOffset);
}
+static void scrollDownAP(Widget w, XEvent *event, String *args,
+ Cardinal *nArgs)
+{
+ syncScrollAP(_scrollDownAP, w, event, args, nArgs);
+}
+
static void scrollLeftAP(Widget w, XEvent *event, String *args,
Cardinal *nArgs)
{
@@ -4232,3 +4282,29 @@
if (!silent)
XBell(XtDisplay(w), 0);
}
+
+void TextScrollGroupJoinWith(TextWidget new, TextWidget prev)
+{
+ TextWidget next = prev->nextScrollGroup;
+
+ next->prevScrollGroup = new;
+ prev->nextScrollGroup = new;
+ new->nextScrollGroup = next;
+ new->prevScrollGroup = prev;
+}
+
+void TextScrollGroupDetach(TextWidget old)
+{
+ TextWidget next = old->nextScrollGroup;
+ TextWidget prev = old->prevScrollGroup;
+
+ next->prevScrollGroup = prev;
+ prev->nextScrollGroup = next;
+ old->nextScrollGroup = old;
+ old->prevScrollGroup = old;
+}
+
+Boolean TextScrollGroupIsSingle(TextWidget text)
+{
+ return (text == text->nextScrollGroup);
+}
diff -ur nedit.orig/source/textDisp.c nedit.syncscroll/source/textDisp.c
--- nedit.orig/source/textDisp.c 2007-07-02 18:26:16.355257281 +0200
+++ nedit.syncscroll/source/textDisp.c 2007-07-03 22:35:09.685088728 +0200
@@ -2902,11 +2902,35 @@
textDisp *textD = (textDisp *)clientData;
int newValue = ((XmScrollBarCallbackStruct *)callData)->value;
int lineDelta = newValue - textD->topLineNum;
-
+ TextWidget text, t;
+
if (lineDelta == 0)
return;
setScroll(textD, newValue, textD->horizOffset, False, True);
+
+ text = (TextWidget)textD->w;
+
+ if (text == text->nextScrollGroup)
+ return;
+
+ /* do synchronous scroll */
+ for (t = text->nextScrollGroup; t != text; t= t->nextScrollGroup) {
+ int newLine;
+ textDisp *tD = t->text.textD;
+ if (lineDelta > 0) {
+ newLine = tD->topLineNum +
+ min(lineDelta, tD->nBufferLines -
+ tD->topLineNum -
+ tD->nVisibleLines + 2);
+ }
+ else {
+ newLine = tD->topLineNum + lineDelta;
+ }
+
+ setScroll(tD, newLine < 1 ? 1 : newLine, 0, True, True);
+ }
}
+
static void hScrollCB(Widget w, XtPointer clientData, XtPointer callData)
{
textDisp *textD = (textDisp *)clientData;
diff -ur nedit.orig/source/text.h nedit.syncscroll/source/text.h
--- nedit.orig/source/text.h 2007-07-02 18:26:16.199244079 +0200
+++ nedit.syncscroll/source/text.h 2007-07-03 21:52:41.955650466 +0200
@@ -169,6 +169,10 @@
void ShowHidePointer(TextWidget w, Boolean hidePointer);
void ResetCursorBlink(TextWidget textWidget, Boolean startsBlanked);
+void TextScrollGroupJoinWith(TextWidget new, TextWidget prev);
+void TextScrollGroupDetach(TextWidget text);
+Boolean TextScrollGroupIsSingle(TextWidget text);
+
#ifdef VMS /* VMS linker doesn't like long names (>31 chars) */
#define HandleAllPendingGraphicsExposeNoExposeEvents HandlePendingExpNoExpEvents
#endif /* VMS */
diff -ur nedit.orig/source/textP.h nedit.syncscroll/source/textP.h
--- nedit.orig/source/textP.h 2007-07-02 18:26:16.247248141 +0200
+++ nedit.syncscroll/source/textP.h 2007-07-03 18:21:21.917827744 +0200
@@ -133,6 +133,8 @@
CorePart core;
XmPrimitivePart primitive;
TextPart text;
+ struct _TextRec *nextScrollGroup;
+ struct _TextRec *prevScrollGroup;
} TextRec;
#endif /* NEDIT_TEXTP_H_INCLUDED */
diff -ur nedit.orig/source/window.c nedit.syncscroll/source/window.c
--- nedit.orig/source/window.c 2007-07-02 18:26:16.256248903 +0200
+++ nedit.syncscroll/source/window.c 2007-07-05 16:56:57.999893111 +0200
@@ -195,6 +195,7 @@
static WindowInfo *inFocusDocument = NULL; /* where we are now */
static WindowInfo *lastFocusDocument = NULL; /* where we came from */
static int DoneWithMoveDocumentDialog;
+static int DoneWithScrollGroupDialog;
static void updateLineNumDisp(const WindowInfo* window);
static int max(const int i1, const int i2);
static void setGutterWidth(const WindowInfo* window, const unsigned reqCols);
@@ -1032,6 +1033,7 @@
}
}
+ TextScrollGroupDetach((TextWidget)window->textArea);
/* remove the window from the global window list, update window menus */
removeFromWindowList(window);
InvalidateWindowMenus();
@@ -2407,6 +2409,8 @@
/* Check for changes to read-only status and/or file modifications */
CheckForChangesToFile(window);
+
+ XtSetSensitive(window->scrollGroupDetachItem, !TextScrollGroupIsSingle((TextWidget)w));
}
static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData)
@@ -4200,6 +4204,9 @@
textD->selectFGPixel, textD->selectBGPixel,
textD->highlightFGPixel,textD->highlightBGPixel,
textD->lineNumFGPixel, textD->cursorFGPixel);
+
+ TextScrollGroupJoinWith((TextWidget)window->textPanes[i],
+ (TextWidget)orgWin->textPanes[i]);
}
/* Set the minimum pane height in the new pane */
@@ -4351,10 +4358,13 @@
window->inode = orgWin->inode;
window->fileClosedAtom = orgWin->fileClosedAtom;
orgWin->fileClosedAtom = None;
-
+
/* copy the text/split panes settings, cursor pos & selection */
cloneTextPanes(window, orgWin);
-
+
+ TextScrollGroupJoinWith((TextWidget)window->textArea,
+ (TextWidget)orgWin->textArea);
+
/* copy undo & redo list */
window->undo = cloneUndoItems(orgWin->undo);
window->redo = cloneUndoItems(orgWin->redo);
@@ -4639,6 +4649,133 @@
XtDestroyWidget(dialog);
}
+static void scrollGroupDocumentCB(Widget dialog, WindowInfo *window,
+ XtPointer call_data)
+{
+ XmSelectionBoxCallbackStruct *cbs = (XmSelectionBoxCallbackStruct *) call_data;
+ DoneWithScrollGroupDialog = cbs->reason;
+}
+
+/*
+** present dialog for selecting a target window to sync this document
+** with. Do nothing if there is only one shell window opened.
+*/
+void ScrollGroupDialog(WindowInfo *window, int paneIndex)
+{
+ WindowInfo *win;
+ TextWidget text, targetText, *textList;
+ int i, nList = 0, nPanes = 0, ac;
+ char tmpStr[MAXPATHLEN + 64];
+ Widget parent, dialog, listBox;
+ XmString *list = NULL;
+ XmString popupTitle, s1;
+ Arg csdargs[20];
+ int *position_list, position_count;
+
+ if (paneIndex < 0)
+ text = (TextWidget)window->lastFocus;
+ else
+ text = (TextWidget)GetPaneByIndex(window, paneIndex);
+
+ nPanes = 0;
+ for (win = WindowList; win; win = win->next)
+ nPanes += win->nPanes + 1;
+ list = (XmStringTable)XtMalloc(nPanes * sizeof(XmString *));
+ textList = (TextWidget *)XtMalloc(nPanes * sizeof(TextWidget *));
+
+ for (win = WindowList; win; win = win->next) {
+ if (0 == win->nPanes) {
+ if (win == window)
+ continue;
+
+ sprintf(tmpStr, "%s%s",
+ win->filenameSet ? win->path : "", win->filename);
+
+ list[nList] = XmStringCreateSimple(tmpStr);
+ textList[nList] = (TextWidget)win->lastFocus;
+ nList++;
+ }
+ else {
+ for (i = 0; i <= win->nPanes; i++) {
+ TextWidget t = i == 0 ? (TextWidget)win->textArea
+ : (TextWidget)win->textPanes[i - 1];
+ if (text == t)
+ continue;
+
+ sprintf(tmpStr, "[%d] %s%s", i,
+ win->filenameSet ? win->path : "", win->filename);
+
+ list[nList] = XmStringCreateSimple(tmpStr);
+ textList[nList] = t;
+ nList++;
+ }
+ }
+ }
+
+ /* stop here if there's no other window to move to */
+ if (!nList) {
+ XtFree((char *)list);
+ XtFree((char *)textList);
+ return;
+ }
+
+ /* create the dialog */
+ parent = window->shell;
+ popupTitle = XmStringCreateSimple("Scroll Group");
+ sprintf(tmpStr, "Sync scrolling %s with window/group", window->filename);
+ s1 = XmStringCreateSimple(tmpStr);
+ ac = 0;
+ XtSetArg(csdargs[ac], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); ac++;
+ XtSetArg(csdargs[ac], XmNdialogTitle, popupTitle); ac++;
+ XtSetArg(csdargs[ac], XmNlistLabelString, s1); ac++;
+ XtSetArg(csdargs[ac], XmNlistItems, list); ac++;
+ XtSetArg(csdargs[ac], XmNlistItemCount, nList); ac++;
+ XtSetArg(csdargs[ac], XmNvisibleItemCount, 12); ac++;
+ XtSetArg(csdargs[ac], XmNautoUnmanage, False); ac++;
+ dialog = CreateSelectionDialog(parent,"syncDocument",csdargs,ac);
+ XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT));
+ XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
+ XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_SELECTION_LABEL));
+ XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)scrollGroupDocumentCB, window);
+ XtAddCallback(dialog, XmNapplyCallback, (XtCallbackProc)scrollGroupDocumentCB, window);
+ XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)scrollGroupDocumentCB, window);
+ XmStringFree(s1);
+ XmStringFree(popupTitle);
+
+ /* free the window list */
+ for (i=0; i < nList; i++)
+ XmStringFree(list[i]);
+ XtFree((char *)list);
+
+ /* disable option if only one document in the window */
+ XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_APPLY_BUTTON));
+
+ s1 = MKSTRING("Join");
+ XtVaSetValues(dialog, XmNokLabelString, s1, NULL);
+ XmStringFree(s1);
+
+ /* default to the first window on the list */
+ listBox = XmSelectionBoxGetChild(dialog, XmDIALOG_LIST);
+ XmListSelectPos(listBox, 1, True);
+
+ /* show the dialog */
+ DoneWithScrollGroupDialog = 0;
+ ManageDialogCenteredOnPointer(dialog);
+ while (!DoneWithScrollGroupDialog)
+ XtAppProcessEvent(XtWidgetToApplicationContext(parent), XtIMAll);
+
+ /* get the window to sync document into */
+ XmListGetSelectedPos(listBox, &position_list, &position_count);
+ targetText = textList[position_list[0] - 1];
+ XtFree((char *)position_list);
+ XtFree((char *)textList);
+ XtDestroyWidget(dialog);
+
+ /* now sync document */
+ if (DoneWithScrollGroupDialog == XmCR_OK)
+ TextScrollGroupJoinWith(text, targetText);
+}
+
static void hideTooltip(Widget tab)
{
Widget tooltip = XtNameToWidget(tab, "*BubbleShell");
diff -ur nedit.orig/source/window.h nedit.syncscroll/source/window.h
--- nedit.orig/source/window.h 2007-07-02 18:26:16.199244079 +0200
+++ nedit.syncscroll/source/window.h 2007-07-03 22:37:31.260309676 +0200
@@ -92,6 +92,7 @@
WindowInfo *MoveDocument(WindowInfo *toWindow, WindowInfo *window);
WindowInfo *DetachDocument(WindowInfo *window);
void MoveDocumentDialog(WindowInfo *window);
+void ScrollGroupDialog(WindowInfo *window, int paneIndex);
WindowInfo* GetTopDocument(Widget w);
Boolean IsTopDocument(const WindowInfo *window);
int IsIconic(WindowInfo *window);
More information about the Develop
mailing list