📄 textedit.c
字号:
caddr_t edit_log_wraps_at = (caddr_t)TEXTSW_INFINITY;#endif int fd, max_fds = GETDTABLESIZE();#define STDERR 2 /* * Init data * Implicitely zeroed: caps_lock_on, handling_signal, * read_only, edited */ edit_icon = icon_create(ICON_IMAGE, &edit_icon_mpr, 0); /* Flush inherited windowfds */ for (fd = STDERR+1; fd < max_fds; fd++) (void)close(fd); cmd_name = *argv; /* Must be BEFORE calls on die() */ current_filename[0] = '\0'; (void) getwd(current_directory); /* Error message is placed into current_directory by getwd */ scratch_lines = defaults_get_integer_check("/Text/Scratch_window", 1, 0, 30, (int *)NULL); checkpoint = defaults_get_integer_check("/Text/Checkpoint_frequency", 0, 0, (int)TEXTSW_INFINITY, (int *)NULL); /* * Create the base frame. * WIN_WIDTH & WIN_HEIGHT=0 used as flags to see if width * or height set in user's argc,argv! * If width still zero later, we'll set it to 80 chars. * If height still zero later, we'll set it to number_of_lines rows. */ base_frame = window_create((Window)NULL, FRAME, WIN_WIDTH, 0, WIN_HEIGHT, 0, WIN_ERROR_MSG, "Unable to create frame\n", FRAME_NO_CONFIRM, TRUE, FRAME_ICON, edit_icon, FRAME_LABEL, "textedit", FRAME_SHOW_LABEL, TRUE, FRAME_CMDLINE_HELP_PROC, my_frame_help, FRAME_ARGC_PTR_ARGV, &argc, argv,#ifdef ecd.help HELP_DATA, "sunview:textedit",#endif 0); if (base_frame == NULL) { (void)fprintf(stderr,"Unable to create frame\n"); exit(1); } number_of_lines = window_get((Window)(LINT_CAST(base_frame)), WIN_HEIGHT) ? 0 : 45; /* * Set icon's font to system font [if user hasn't set icon font], * but AFTER window_create has a chance to change it from the * built-in font. * If the user supplies a label, use it and don't override * with our's later. * Note that we get the icon from the Frame in case user * over-rides via argc, argv! */ edit_icon = window_get(base_frame, FRAME_ICON); user_label = (int)icon_get(edit_icon, ICON_LABEL); if (!icon_get(edit_icon, ICON_FONT)) { (void)icon_set(edit_icon, ICON_FONT, pw_pfsysopen(), 0); if (!icon_get(edit_icon, ICON_FONT)) die("Cannot get default font.\n", (char *)NULL, (char *)NULL); (void)window_set(base_frame, FRAME_ICON, edit_icon, 0); } /* * Interpose on the destroy function so we can tell user * what to do. (Avoids default veto message) */ (void) notify_interpose_destroy_func(base_frame, my_destroy_func); /* * Pick up command line arguments to modify textsw behavior. * Notes: FRAME_ARGC_PTR_ARGV above has stripped window flags. * case OPTION_MARGIN is used to compute WIN_WIDTH. */#ifndef lint margin = (int)textsw_get(TEXTSW, TEXTSW_LEFT_MARGIN);#endif argc--; argv++; /* Skip the cmd name */ while ((argc--) && (attrc < ATTR_STANDARD_SIZE)) { if (argv[0][0] == '-') { extern int match_in_table(); int option = match_in_table(&(argv[0][1]), option_names); if (option < 0 || option >= optioncount) { die(argv[0], " is not a valid option.\n", (char *)NULL); } switch (1<<(option/2)) { case OPTION_NUMBER_OF_LINES: if (argc > 0) { number_of_lines = atoi(argv[1]); argc--, argv++; } break; case OPTION_SCRATCH_WINDOW: if (argc > 0) { scratch_lines = atoi(argv[1]); argc--, argv++; } break; case OPTION_READ_ONLY: read_only = 1; if ((argc > 0) && (argv[1][0] != '-')) { argc--, argv++; read_only = !off(argv[0]); } break; case OPTION_AUTO_INDENT: textsw_attrs[attrc++] = (caddr_t) TEXTSW_AUTO_INDENT; textsw_attrs[attrc] = (caddr_t) 1; if ((argc > 0) && (argv[1][0] != '-')) { argc--, argv++; textsw_attrs[attrc] = (caddr_t) !off(argv[0]); } attrc++; break; case OPTION_ADJUST_IS_PD: textsw_attrs[attrc++] = (caddr_t) TEXTSW_ADJUST_IS_PENDING_DELETE; textsw_attrs[attrc] = (caddr_t) 1; if ((argc > 0) && (argv[1][0] != '-')) { argc--, argv++; textsw_attrs[attrc] = (caddr_t) !off(argv[0]); } attrc++; break; case OPTION_ALWAYS_OVERWRITE: textsw_attrs[attrc++] = (caddr_t) TEXTSW_CONFIRM_OVERWRITE; textsw_attrs[attrc] = (caddr_t) 0; if ((argc > 0) && (argv[1][0] != '-')) { argc--, argv++; textsw_attrs[attrc] = (caddr_t) off(argv[0]); } attrc++; break;#ifdef DEBUG case OPTION_EDIT_LOG_WRAPS_AT: GET_INT_ATTR_VAL(edit_log_wraps_at) break;#endif case OPTION_LOWER_CONTEXT: textsw_attrs[attrc++] = (caddr_t) TEXTSW_LOWER_CONTEXT; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break;#ifdef DEBUG case OPTION_MALLOC_DEBUG_LEVEL: textsw_attrs[attrc++] = (caddr_t) TEXTSW_MALLOC_DEBUG_LEVEL; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break;#endif case OPTION_MARGIN: textsw_attrs[attrc++] = (caddr_t) TEXTSW_LEFT_MARGIN; margin = atoi(argv[1]); GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break; case OPTION_MULTI_CLICK_SPACE: textsw_attrs[attrc++] = (caddr_t) TEXTSW_MULTI_CLICK_SPACE; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break; case OPTION_MULTI_CLICK_TIMEOUT: textsw_attrs[attrc++] = (caddr_t) TEXTSW_MULTI_CLICK_TIMEOUT; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break; case OPTION_TAB_WIDTH: textsw_attrs[attrc++] = (caddr_t) TEXTSW_TAB_WIDTH; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break; case OPTION_UNDO_HISTORY: textsw_attrs[attrc++] = (caddr_t) TEXTSW_HISTORY_LIMIT; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break; case OPTION_UPPER_CONTEXT: textsw_attrs[attrc++] = (caddr_t) TEXTSW_UPPER_CONTEXT; GET_INT_ATTR_VAL(textsw_attrs[attrc++]) break; case OPTION_CHECKPOINT_FREQUENCY: if (argc > 0) { checkpoint = atoi(argv[1]); argc--, argv++; } break; default: die("Unrecognized command line option.", (char *)NULL, (char *)NULL); break; } } else if (file_to_edit == NULL) { file_to_edit = argv[0]; } else { die("Too many files specified.", (char *)NULL, (char *)NULL); } argv++; } textsw_attrs[attrc] = 0; /* A-V list terminator */ /* * Set width to 80 chars if not set by user. *//* Add term of charwidth-1 to insure that there is enough width */ if (!window_get(base_frame, WIN_WIDTH)) (void) window_set(base_frame, WIN_WIDTH, 81 * (int) window_get(base_frame, WIN_COLUMN_WIDTH) - 1 + margin + 2 + scrollbar_get((Scrollbar) (LINT_CAST(SCROLLBAR)), SCROLL_THICKNESS) + (int) window_get(base_frame, WIN_LEFT_MARGIN) + (int) window_get(base_frame, WIN_RIGHT_MARGIN), 0); else (void) window_set(base_frame, WIN_WIDTH, ((int) window_get(base_frame, WIN_COLUMNS) + 1) * (int) window_get(base_frame, WIN_COLUMN_WIDTH) - 1 + margin + 2 + scrollbar_get((Scrollbar) (LINT_CAST(SCROLLBAR)), SCROLL_THICKNESS) + (int) window_get(base_frame, WIN_LEFT_MARGIN) + (int) window_get(base_frame, WIN_RIGHT_MARGIN), 0); /* * Create subwindows */ if (scratch_lines > 0) { textsw = (Textsw)(LINT_CAST( window_create((Window)base_frame, TEXTSW, ATTR_LIST, textsw_attrs, TEXTSW_STATUS, &status, TEXTSW_CONTENTS, "Scratch window", TEXTSW_DISABLE_CD, 1, TEXTSW_DISABLE_LOAD, 1, TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY, WIN_ROWS, scratch_lines, WIN_ERROR_MSG, "Unable to create subwindow\n", 0))); switch (status) { case TEXTSW_STATUS_OKAY: if (textsw) break; /* else fall through */ default: die("Cannot create textsw, exiting!\n", (char *)NULL, (char *)NULL); } } read_only = (read_only & (file_to_edit != NULL));#ifdef DEBUG if (edit_log_wraps_at != (caddr_t)TEXTSW_INFINITY) { textsw_attrs[attrc++] = (caddr_t) TEXTSW_WRAPAROUND_SIZE; textsw_attrs[attrc++] = edit_log_wraps_at; textsw_attrs[attrc] = 0; }#endif if ((file_to_edit != NULL) && (stat(file_to_edit, &stb) < 0)) { int result; Event event; char msg[200]; (void) sprintf(msg, "Filename '%s' does not exist.", file_to_edit); result = alert_prompt( (Frame)NULL, (Event *)NULL, ALERT_MESSAGE_STRINGS, msg, "Please confirm creation of new", "file for textedit.", 0, ALERT_BUTTON_YES, "Confirm", ALERT_BUTTON_NO, "Cancel", 0); if (result == ALERT_YES) { if (open(file_to_edit, O_CREAT, 0666) == -1) die("Cannot create new file, exiting!\n", (char *)NULL, (char *)NULL); } else exit(4); } textsw = (Textsw)(LINT_CAST(window_create(base_frame, TEXTSW, ATTR_LIST, textsw_attrs, TEXTSW_STATUS, &status, TEXTSW_READ_ONLY, read_only, TEXTSW_FILE, file_to_edit, TEXTSW_NOTIFY_PROC, set_name_frame, TEXTSW_CHECKPOINT_FREQUENCY, checkpoint, WIN_ERROR_MSG, "Unable to create subwindow\n", 0))); switch (status) { case TEXTSW_STATUS_CANNOT_OPEN_INPUT: die("Cannot open file '", file_to_edit, "', exiting!\n"); case TEXTSW_STATUS_OKAY: if (textsw) break; /* else fall through */ default: die("Cannot create textsw, exiting!\n", (char *)NULL, (char *)NULL); } /* * Setup signal handlers. */ (void)notify_set_signal_func(base_frame, mysigproc, SIGINT, NOTIFY_ASYNC); (void)notify_set_signal_func(base_frame, mysigproc, SIGXCPU, NOTIFY_ASYNC); (void)notify_set_signal_func(base_frame, mysigproc, SIGBUS, NOTIFY_ASYNC); (void)notify_set_signal_func(base_frame, mysigproc, SIGHUP, NOTIFY_ASYNC); (void)notify_set_signal_func(base_frame, mysigproc, SIGILL, NOTIFY_ASYNC); (void)notify_set_signal_func(base_frame, mysigproc, SIGSEGV, NOTIFY_ASYNC); (void)notify_set_signal_func(base_frame, mysigproc, SIGFPE, NOTIFY_ASYNC); /* * Install us in tree of windows */ if (number_of_lines) { (void)window_set((Window)(LINT_CAST(textsw)), WIN_ROWS, number_of_lines, 0); (void)window_fit_height(base_frame); } window_main_loop(base_frame); exit(0);}/* * SIGNAL handlers *//* ARGSUSED */static Notify_valuemysigproc(me, sig, when) Notify_client me; int sig; Notify_signal_mode when;{ char name_to_use[MAXNAMLEN]; int pid = getpid(); int was_SIGILL = (sig == SIGILL); struct sigvec vec; if (handling_signal == 2) _exit(3); if (handling_signal++ == 1) { (void)fprintf(stderr, "Signal catcher called recursively: "); goto Die; } if (sig == SIGINT) { if (window_get((Window)(LINT_CAST(textsw)), TEXTSW_MODIFIED)) { (void)window_destroy(base_frame); /* It will be vetoed */ handling_signal = 0; } else { /* Skip more user confirmation - just die (but cleanly)! */ (void) notify_post_destroy(base_frame, DESTROY_PROCESS_DEATH, NOTIFY_IMMEDIATE); (void) notify_stop(); } return(NOTIFY_DONE); } (void)sprintf(name_to_use, "textedit.%d", pid); (void)fprintf(stderr, "attempting Store to %s ... ", name_to_use); (void)fflush(stderr); if (textsw_store_file(textsw, name_to_use, 0, 0) == 0) goto Done; (void)sprintf(name_to_use, "/usr/tmp/textedit.%d", pid); (void)fprintf(stderr, "failed!\nAttempting Store to %s ... ", name_to_use); (void)fflush(stderr); if (textsw_store_file(textsw, name_to_use, 0, 0) == 0) goto Done; (void)sprintf(name_to_use, "/tmp/textedit.%d", pid); (void)fprintf(stderr, "failed!\nAttempting Store to %s ... ", name_to_use); (void)fflush(stderr); if (textsw_store_file(textsw, name_to_use, 0, 0) == 0) goto Done; (void)fprintf(stderr, "failed!\nSorry, cannot save your edits: "); goto Die;Done: (void)fprintf(stderr, "finished; ");Die: (void)fprintf(stderr, "aborting for post-mortem ...\n"); (void)fflush(stderr); (void)sigsetmask(0); /* Make sure signals get through */ if (was_SIGILL) {#ifndef lint char dummy, *bad_ptr = 0; /* (void)signal(SIGSEGV, SIG_DFL); /* Make sure 0 deref dumps. */ vec.sv_handler = SIG_DFL; vec.sv_mask = vec.sv_onstack = 0; sigvec(SIGSEGV, &vec, 0); dummy = *bad_ptr;#endif } else { /* (void)signal(SIGILL, SIG_DFL); /* Make sure abort() dumps. */ vec.sv_handler = SIG_DFL; vec.sv_mask = vec.sv_onstack = 0; sigvec(SIGILL, &vec, 0); abort(); } return(NOTIFY_DONE);}/* * Misc. utilities */staticdie(msg1, msg2, msg3) char *msg1, *msg2, *msg3;{ char *dummy = ""; (void)fprintf(stderr, "%s: %s%s%s\n", cmd_name, msg1, (msg2?msg2:dummy), (msg3?msg3:dummy)); exit(4);}static intoff(str) char *str;{ return ((strcmp(str, "off") == 0) || (strcmp(str, "Off") == 0) || (strcmp(str, "OFF") == 0) );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -