This is support.c in view mode; [Download] [Up]
/* Miscellaneous support functions (such as tilda expansion). Copyright (C) 1993 Sebastiano Vigna This file is part of ne, the nice editor. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! */ #include "ne.h" #ifdef _AMIGA #include <proto/dos.h> #else #include <pwd.h> #endif /* Some systems do not define _POSIX_VDISABLE. We try to establish a reasonable value. */ #ifndef _POSIX_VDISABLE #ifdef CDEL #define _POSIX_VDISABLE CDEL #else #define _POSIX_VDISABLE 255 #endif #endif /* This is the assert function. It appears that its number of arguments is different on different ANSI C compilers. Better to redefine it. */ #ifndef NODEBUG void __assert(int x, char *expr, char *file, int line) { if (!x) fprintf(stderr, "%s can't be false at line %d of %s!\n", expr, line, file); } #endif /* This function returns a pointer to a tilde-expanded version of the string pointed to by filename. The string should not be free()ed, since it is tracked locally. Note that this function can return the same pointer which is passed, in case no tilde expansion has to be performed. */ #ifndef _AMIGA const char *tilde_expand(const char *filename) { static char *expanded_filename; char *home_dir, *p; struct passwd *passwd = NULL; if (!filename) return(NULL); if (filename[0] != '~') return(filename); if (filename[1] == '/') { home_dir = getenv("HOME"); filename++; } else { const char *s; char *t; s = filename+1; while(*s && *s != '/') s++; if (t = malloc(s - filename)) { memcpy(t, filename+1, s-filename-1); t[s-filename-1] = 0; passwd = getpwnam(t); free(t); } if (!passwd) return(filename); filename = s; home_dir = passwd->pw_dir; } if (p = realloc(expanded_filename, strlen(filename)+strlen(home_dir)+1)) { strcat(strcpy(expanded_filename = p, home_dir), filename); return(expanded_filename); } return(filename); } #endif /* Given a pathname, this function returns a pointer to the real file name (i.e., the pointer points inside the string passed). */ const char *file_part(const char *pathname) { const char *p; if (!pathname) return(NULL); #ifdef _AMIGA return((const char *)FilePart((char *)pathname)); #else p = pathname+strlen(pathname); while(p > pathname && *(p-1) != '/') p--; return(p); #endif } /* This function duplicates a string. */ char *str_dup(const char *s) { char *dup; if (!s) return(NULL); dup = malloc(strlen(s)+1); if (dup) strcpy(dup, s); return(dup); } /* This function is a useful shortcut for output_chars()ing a NULL-terminated string. */ void output_string(const char *s) { assert(s != NULL); output_chars(s, strlen(s)); } /* This function is typically passed to qsort() in order to sort an array of string pointers. */ int strcmpp(const void *a, const void *b) { return(strcmp(*(const char **)a, *(const char **)b)); } #ifdef _AMIGA /* This function supplies a getenv() simulation on the Amiga. Unfortunately, the SAS/C version of getenv() does not look at the local variables, which are the only ones we are really interested in... */ char *getenv(const char *name) { static char buffer[2048]; if (GetVar((char *)name, buffer, sizeof(buffer), 0) > -1) return(buffer); else return(NULL); } #endif /* This function sets the "interactive I/O mode" of the terminal. It suitably sets the mode bits of the termios structure, and then transmits various capability strings by calling set_terminal_modes(). This function assumes that the terminfo database has been properly initialized. The old_termios structure records the original state of the terminal interface. Note that if terminal_reset is TRUE, we assume that resetterm() has been called in the past (likely by unset_interactive_mode()), so we call fixterm(). Usually, the first invocation of set_interactive_mode() is after term_init(), which calls setupterm(), so that fixterm() is not necessary. */ #ifndef _AMIGA static struct termios termios, old_termios; #endif static int terminal_reset; void set_interactive_mode(void) { if (terminal_reset) { /* This call restores some terminal characteristics which are felt necessary by terminfo. */ fixterm(); terminal_reset = FALSE; } #ifndef _AMIGA tcgetattr(0, &termios); old_termios = termios; termios.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | ISTRIP | IEXTEN); termios.c_iflag |= IGNBRK; termios.c_oflag &= ~OPOST; termios.c_lflag &= ~(ICANON | ECHO); termios.c_lflag |= ISIG; termios.c_cflag &= ~PARENB; termios.c_cflag |= CS8; termios.c_cc[VTIME] = 0; termios.c_cc[VMIN] = 1; /* Now we keep the kernel from intercepting any keyboard input in order to turn it into a signal. Note that some signals, such as dsusp on BSD, are not trackable here. They have to be disabled through suitable commands (for instance, `stty dsusp ^-'). */ termios.c_cc[VSUSP] = _POSIX_VDISABLE; termios.c_cc[VQUIT] = _POSIX_VDISABLE; termios.c_cc[VKILL] = _POSIX_VDISABLE; termios.c_cc[VINTR] = _POSIX_VDISABLE; /* Control-\ is the stop control sequence for ne. */ termios.c_cc[VQUIT] = termios.c_cc[VINTR] = '\\'-'@'; tcsetattr(0, TCSADRAIN, &termios); #else SetMode(Input(), 1); #endif /* This ensures that a physical read will be performed at each getchar(). */ setbuf(stdin, NULL); /* We enable the keypad, cursor addressing, etc. */ set_terminal_modes(); } /* This function undoes the work of the previous one, in reverse order. It assumes the old_termios has been filled with the old termios structure. It sets terminal_reset to TRUE, so that fixterm() will be called on the next invocation of set_interactive_mode(). */ void unset_interactive_mode(void) { /* We move the cursor on the last line, clear it, and output a CR, so that the kernel can track the cursor position. Note that clear_to_eol() can move the cursor. */ move_cursor(lines-1, 0); clear_to_eol(); move_cursor(lines-1, 0); putchar('\r'); /* Now we disable the keypad, cursor addressing, etc. fflush() guarantees that tcsetattr() won't clip part of the capability strings output by reset_terminal_modes(). */ reset_terminal_modes(); fflush(stdout); /* Now we restore all the flags in the termios structure to the state they were before us. */ #ifndef _AMIGA tcsetattr(0, TCSANOW, &old_termios); #else SetMode(Input(), 0); #endif /* Finally, we undo the changes made by the terminfo call setupterm(). */ resetterm(); terminal_reset = TRUE; } /* This function computes the TAB-expanded length of a line descriptor up to a certain position. The position can be greater than the line length, the usual convention of infinite expansion via spaces being in place. */ int calc_len(line_desc *ld, int n, int tab_size) { int i, len; for(i=len=0; i<n; i++) { if (i >= ld->line_len || ld->line[i] != '\t') len++; else len += tab_size - len%tab_size; } return(len); } /* This function inverts the computation of calc_len. For a given horizontal position on a line descriptor, the index of the character "containing" that position is given. For a non-TAB character, this means that calc_len(index+1) = n. For a TAB character, calc_len(index+1) >= n, since the nth horizontal position could fall inside the expansion of the TAB. */ int calc_pos(line_desc *ld, int n, int tab_size) { int i, len; for(i=len=0; i<ld->line_len && len<n; i++) if (ld->line[i] != '\t') len++; else len += tab_size - len%tab_size; return(i); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.