📄 window.c
字号:
} window_adjust_pagetop (prev); window_adjust_pagetop (next); } } if (prev) prev->flags |= W_UpdateWindow; if (next) next->flags |= W_UpdateWindow; window->flags |= W_UpdateWindow; window_adjust_pagetop (window);}/* Tile all of the windows currently displayed in the global variable WINDOWS. If argument STYLE is TILE_INTERNALS, tile windows displaying internal nodes as well, otherwise do not change the height of such windows. */voidwindow_tile_windows (style) int style;{ WINDOW *win, *last_adjusted; int numwins, avail, per_win_height, leftover; int do_internals; numwins = avail = 0; do_internals = (style == TILE_INTERNALS); for (win = windows; win; win = win->next) if (do_internals || !win->node || (win->node->flags & N_IsInternal) == 0) { avail += win->height; numwins++; } if (numwins <= 1 || !the_screen->height) return; /* Find the size for each window. Divide the size of the usable portion of the screen by the number of windows. */ per_win_height = avail / numwins; leftover = avail - (per_win_height * numwins); last_adjusted = (WINDOW *)NULL; for (win = windows; win; win = win->next) { if (do_internals || !win->node || (win->node->flags & N_IsInternal) == 0) { last_adjusted = win; win->height = per_win_height; } } if (last_adjusted) last_adjusted->height += leftover; /* Readjust the first_row of every window in the chain. */ for (win = windows; win; win = win->next) { if (win->prev) win->first_row = win->prev->first_row + win->prev->height + 1; window_adjust_pagetop (win); win->flags |= W_UpdateWindow; }}/* Toggle the state of line wrapping in WINDOW. This can do a bit of fancy redisplay. */voidwindow_toggle_wrap (window) WINDOW *window;{ if (window->flags & W_NoWrap) window->flags &= ~W_NoWrap; else window->flags |= W_NoWrap; if (window != the_echo_area) { char **old_starts; int old_lines, old_pagetop; old_starts = window->line_starts; old_lines = window->line_count; old_pagetop = window->pagetop; calculate_line_starts (window); /* Make sure that point appears within this window. */ window_adjust_pagetop (window); /* If the pagetop hasn't changed maybe we can do some scrolling now to speed up the display. Many of the line starts will be the same, so scrolling here is a very good optimization.*/ if (old_pagetop == window->pagetop) display_scroll_line_starts (window, old_pagetop, old_starts, old_lines); maybe_free (old_starts); } window->flags |= W_UpdateWindow;}/* Set WINDOW to display NODE. */voidwindow_set_node_of_window (window, node) WINDOW *window; NODE *node;{ window->node = node; window->pagetop = 0; window->point = 0; recalculate_line_starts (window); window->flags |= W_UpdateWindow; window_adjust_pagetop (window); window_make_modeline (window);}/* Delete WINDOW from the list of known windows. If this window was the active window, make the next window in the chain be the active window. If the active window is the next or previous window, choose that window as the recipient of the extra space. Otherwise, prefer the next window. */voidwindow_delete_window (window) WINDOW *window;{ WINDOW *next, *prev, *window_to_fix; next = window->next; prev = window->prev; /* You cannot delete the only window or a permanent window. */ if ((!next && !prev) || (window->flags & W_WindowIsPerm)) return; if (next) next->prev = prev; if (!prev) windows = next; else prev->next = next; if (window->line_starts) free (window->line_starts); if (window->modeline) free (window->modeline); if (window == active_window) { /* If there isn't a next window, then there must be a previous one, since we cannot delete the last window. If there is a next window, prefer to use that as the active window. */ if (next) active_window = next; else active_window = prev; } if (next && active_window == next) window_to_fix = next; else if (prev && active_window == prev) window_to_fix = prev; else if (next) window_to_fix = next; else if (prev) window_to_fix = prev; else window_to_fix = windows; if (window_to_fix->first_row > window->first_row) { int diff; /* Try to adjust the visible part of the node so that as little text as possible has to move. */ diff = window_to_fix->first_row - window->first_row; window_to_fix->first_row = window->first_row; window_to_fix->pagetop -= diff; if (window_to_fix->pagetop < 0) window_to_fix->pagetop = 0; } /* The `+ 1' is to offset the difference between the first_row locations. See the code in window_make_window (). */ window_to_fix->height += window->height + 1; window_to_fix->flags |= W_UpdateWindow; free (window);}/* For every window in CHAIN, set the flags member to have FLAG set. */voidwindow_mark_chain (chain, flag) WINDOW *chain; int flag;{ register WINDOW *win; for (win = chain; win; win = win->next) win->flags |= flag;}/* For every window in CHAIN, clear the flags member of FLAG. */voidwindow_unmark_chain (chain, flag) WINDOW *chain; int flag;{ register WINDOW *win; for (win = chain; win; win = win->next) win->flags &= ~flag;}/* Return the number of characters it takes to display CHARACTER on the screen at HPOS. */intcharacter_width (character, hpos) int character, hpos;{ int printable_limit = 127; int width = 1; if (ISO_Latin_p) printable_limit = 255; if (character > printable_limit) width = 3; else if (iscntrl (character)) { switch (character) { case '\r': case '\n': width = the_screen->width - hpos; break; case '\t': width = ((hpos + 8) & 0xf8) - hpos; break; default: width = 2; } } else if (character == DEL) width = 2; return (width);}/* Return the number of characters it takes to display STRING on the screen at HPOS. */intstring_width (string, hpos) char *string; int hpos;{ register int i, width, this_char_width; for (width = 0, i = 0; string[i]; i++) { this_char_width = character_width (string[i], hpos); width += this_char_width; hpos += this_char_width; } return (width);}/* Quickly guess the approximate number of lines to that NODE would take to display. This really only counts carriage returns. */intwindow_physical_lines (node) NODE *node;{ register int i, lines; char *contents; if (!node) return (0); contents = node->contents; for (i = 0, lines = 1; i < node->nodelen; i++) if (contents[i] == '\n') lines++; return (lines);}/* Calculate a list of line starts for the node belonging to WINDOW. The line starts are pointers to the actual text within WINDOW->NODE. */voidcalculate_line_starts (window) WINDOW *window;{ register int i, hpos; char **line_starts = (char **)NULL; int line_starts_index = 0, line_starts_slots = 0; int bump_index; NODE *node; window->line_starts = (char **)NULL; window->line_count = 0; node = window->node; if (!node) return; /* Grovel the node starting at the top, and for each line calculate the width of the characters appearing in that line. Add each line start to our array. */ i = 0; hpos = 0; bump_index = 0; while (i < node->nodelen) { char *line = node->contents + i; unsigned int cwidth, c; add_pointer_to_array (line, line_starts_index, line_starts, line_starts_slots, 100, char *); if (bump_index) { i++; bump_index = 0; } while (1) { c = node->contents[i]; cwidth = character_width (c, hpos); /* If this character fits within this line, just do the next one. */ if ((hpos + cwidth) < window->width) { i++; hpos += cwidth; continue; } else { /* If this character would position the cursor at the start of the next printed screen line, then do the next line. */ if (c == '\n' || c == '\r' || c == '\t') { i++; hpos = 0; break; } else { /* This character passes the window width border. Postion the cursor after the printed character, but remember this line start as where this character is. A bit tricky. */ /* If this window doesn't wrap lines, proceed to the next physical line here. */ if (window->flags & W_NoWrap) { hpos = 0; while (i < node->nodelen && node->contents[i] != '\n') i++; if (node->contents[i] == '\n') i++; } else { hpos = the_screen->width - hpos; bump_index++; } break; } } } } window->line_starts = line_starts; window->line_count = line_starts_index;}/* Given WINDOW, recalculate the line starts for the node it displays. */voidrecalculate_line_starts (window) WINDOW *window;{ maybe_free (window->line_starts); calculate_line_starts (window);}/* Global variable control redisplay of scrolled windows. If non-zero, it is the desired number of lines to scroll the window in order to make point visible. A user might set this to 1 for smooth scrolling. If set to zero, the line containing point is centered within the window. */int window_scroll_step = 0;/* Adjust the pagetop of WINDOW such that the cursor point will be visible. */voidwindow_adjust_pagetop (window) WINDOW *window;{ register int line = 0; char *contents; if (!window->node) return; contents = window->node->contents; /* Find the first printed line start which is after WINDOW->point. */ for (line = 0; line < window->line_count; line++) { char *line_start; line_start = window->line_starts[line]; if ((line_start - contents) > window->point) break; } /* The line index preceding the line start which is past point is the one containing point. */ line--; /* If this line appears in the current displayable page, do nothing. Otherwise, adjust the top of the page to make this line visible. */ if ((line < window->pagetop) || (line - window->pagetop > (window->height - 1))) { /* The user-settable variable "scroll-step" is used to attempt to make point visible, iff it is non-zero. If that variable is zero, then the line containing point is centered within the window. */ if (window_scroll_step < window->height) { if ((line < window->pagetop) && ((window->pagetop - window_scroll_step) <= line)) window->pagetop -= window_scroll_step; else if ((line - window->pagetop > (window->height - 1)) && ((line - (window->pagetop + window_scroll_step) < window->height))) window->pagetop += window_scroll_step; else window->pagetop = line - ((window->height - 1) / 2); } else window->pagetop = line - ((window->height - 1) / 2); if (window->pagetop < 0) window->pagetop = 0; window->flags |= W_UpdateWindow; }}/* Return the index of the line containing point. */intwindow_line_of_point (window) WINDOW *window;{ register int i, start = 0; /* Try to optimize. Check to see if point is past the pagetop for this window, and if so, start searching forward from there. */ if ((window->pagetop > -1 && window->pagetop < window->line_count) && (window->line_starts[window->pagetop] - window->node->contents) <= window->point) start = window->pagetop; for (i = start; i < window->line_count; i++) { if ((window->line_starts[i] - window->node->contents) > window->point) break; } return (i - 1);}/* Get and return the goal column for this window. */intwindow_get_goal_column (window) WINDOW *window;{ if (!window->node) return (-1); if (window->goal_column != -1) return (window->goal_column); /* Okay, do the work. Find the printed offset of the cursor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -