Esempio n. 1
0
int				sh_loop(t_info *info)
{
	int			ret;
	int			multi;

	ret = 1;
	sh_get_path(info);
	ft_printf("\033[31m%s\033[39m $> ", info->cursdir);
	while ((ret = get_next_line(0, &info->line)) > 0)
	{
		UNSET(info->sig, BIT_A);
		UNSET(info->opt, OPT_A);
		if (!(multi = sh_multi(info)))
		{
			sh_parse(info);
			info->status = sh_exec(info, info->env, &info->args[1]);
		}
		sh_get_path(info);
		ft_printf("\033[31m%s\033[39m $> ", info->cursdir);
		ft_tabdel(&info->args);
		free(info->line);
	}
	if (ret == -1)
		return (EXIT_FAILURE);
	return (EXIT_SUCCESS);
}
Esempio n. 2
0
/******************************* Main Program Code *************************/
int main(void)
{
// enable motor#1
    DDRA = 0b00001100;
    
// initialize the LCD controller as determined by the defines (LCD instructions)
    lcd_init_4d();                                  // initialize the LCD display for a 4-bit interface

// endless loop
    while(1) {
		lcd_clear_line_4d(lcd_LineOne);
		_delay_ms(500);
    	// display the first line of information
		lcd_write_string_line_4d("Motor Clockwise", lcd_LineOne);
		// rotate motor
	    UNSET(PORTA, PIN(2));
	    SET(PORTA, PIN(3));
	    // clear LCD
		lcd_clear_line_4d(lcd_LineTwo);
		_delay_ms(500);
    	// display the first line of information
		lcd_write_string_line_4d("Counter Clockwiz", lcd_LineTwo);
		// rotate motor
	    SET(PORTA, PIN(2));
	    UNSET(PORTA, PIN(3));
    }
    return 0;
}
Esempio n. 3
0
// The daemon_init function provides an interface to the main thread
// to start the daemon. It should only be called once and will run
// in the main thread.
void daemon_init(DaemonComm *dc)
{
    // Initialize the Daemon Communication Struct.
    // This struct is used to pass information from the
    // main thread to the daemon thread.
    UNSET(dc->new_code);
    UNSET(dc->in_hw);
    dc->new_code_address = NULL;
    dc->new_code_size = 0;

    // Create the daemon thread.
    hthread_create(&dc->tid, NULL, daemon_thread, (void *)dc);
}
Esempio n. 4
0
int				sh_env(t_info *info)
{
	int			i;
	t_info		context;

	sh_context(info, &context);
	UNSET(context.opt, OPT_A);
	i = 1;
	while (env_opt(context.args[i], &context))
		i++;
	if (GET(context.opt, OPT_I))
		env_i(&context, i);
	else if (!context.args[1])
	{
		sh_printenv(&context);
		return (EXIT_SUCCESS);
	}
	else
		env_set(&context);
	if (ft_strequ(context.args[0], "cd"))
		return (EXIT_SUCCESS);
	else if (context.args[0])
		sh_exec(&context);
	else
		sh_printenv(&context);
	sh_clear_context(&context);
	return (EXIT_SUCCESS);
}
Esempio n. 5
0
File: chmod.c Progetto: akat1/impala
int
sc_chmod(thread_t *t, syscall_result_t *r, chmod_args_t *args)
{
    int res=0;
    proc_t *p = t->thr_proc;
    vnode_t *node;
    char pname[PATH_MAX];
    if((res = copyinstr(pname, args->fname, PATH_MAX)))
        return res;

    res = vfs_lookup(p->p_curdir, &node, pname, t, LKP_NORMAL);
    if(res)
        return res;
    vattr_t va;
    va.va_mask=VATTR_ALL;
    if((res = VOP_GETATTR(node, &va)))
        goto err;
    res = -EPERM;
    if(p->p_cred->p_euid != 0 && p->p_cred->p_euid != va.va_uid)
        goto err;
    mode_t mode = args->mode & 07777;
    if(ISSET(mode, S_ISGID) && p->p_cred->p_euid!=0 
        && va.va_gid!=p->p_cred->p_egid)
        UNSET(mode, S_ISGID); //mamy prawo kasować bit suid/sgid?
    va.va_mask = VATTR_MODE;
    va.va_mode = mode;
    if((res = VOP_SETATTR(node, &va)))
        goto err;
    vrele(node);    
    return 0;
err:
    vrele(node);
    return res;
}
Esempio n. 6
0
// The daemon_create_thread is used by the main thread to create user
// threads. This will run in the main thread.
void daemon_create_thread(DaemonComm *dc, byte *code, unsigned int code_size)
{
    // Change the state of dc to reflect the presence of new bytecode to execute.
    SET(dc->new_code);
    UNSET(dc->in_hw);   // (HW/SW is unspecified)
    dc->new_code_address = code;
    dc->new_code_size = code_size;

    // Yield to allow the daemon thread to process this create.
    hthread_yield();
}
Esempio n. 7
0
__interrupt void USCI0RX_ISR(void)
{
	while (!(IFG2 & UCA0TXIFG));
	if(~IS_SET(RECEIVED)){
		if(RX == START_BYTE && ~IS_SET(RECEIVING)){
			SET(RECEIVING);
		}
		else if(RX != END_BYTE && IS_SET(RECEIVING)){
			buffer[bufferCursor] = RX;
			if(++bufferCursor == BUF_SIZE){
				UNSET(RECEIVING);
				SET(RECEIVED);
			}
		}
		else if(RX == END_BYTE && IS_SET(RECEIVING)){
			UNSET(RECEIVING);
			SET(RECEIVED);
		}
	}
}
Esempio n. 8
0
/* Display a message on the statusbar, and set disable_cursorpos to
 * true, so that the message won't be immediately overwritten if
 * constant cursor position display is on. */
void statusbar(const char *msg, ...)
{
	va_list ap;
	char *bar, *foo;
	size_t start_x;
	bool old_whitespace;

	va_start(ap, msg);

	/* Curses mode is turned off.  If we use wmove() now, it will muck
	 * up the terminal settings.  So we just use vfprintf(). */
	if (isendwin()) {
		vfprintf(stderr, msg, ap);
		va_end(ap);
		return;
	}

	blank_statusbar();

	old_whitespace = ISSET(WHITESPACE_DISPLAY);
	UNSET(WHITESPACE_DISPLAY);
	bar = charalloc(mb_cur_max() * (COLS - 3));
	vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
	va_end(ap);
	foo = display_string(bar, 0, COLS - 4, false);
	free(bar);
	if (old_whitespace) {
		SET(WHITESPACE_DISPLAY);
	}
	start_x = (COLS - strlenpt(foo) - 4) / 2;

	wmove(bottomwin, 0, start_x);
	set_color(bottomwin, interface_colors[STATUS_BAR]);
	waddstr(bottomwin, "[ ");
	waddstr(bottomwin, foo);
	free(foo);
	waddstr(bottomwin, " ]");
	clear_color(bottomwin, interface_colors[STATUS_BAR]);
	wnoutrefresh(bottomwin);
	reset_cursor();
	wnoutrefresh(edit);
	/* Leave the cursor at its position in the edit window, not in
	 * the statusbar. */

	disable_cursorpos = true;

	/* If we're doing quick statusbar blanking, and constant cursor
	 * position display is off, blank the statusbar after only one
	 * keystroke.  Otherwise, blank it after twenty-six keystrokes, as
	 * Pico does. */
	statusblank = ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 : 26;
}
Esempio n. 9
0
void		process_modifier(t_mod *m)
{
    if (ft_strchr("DOCU", m->convers))
    {
        UNSET(m->modif, MOD_ALL);
        SET(m->modif, MOD_L);
        m->convers = ft_tolower(m->convers);
    }
    if (m->convers == 's' && GET(m->modif, MOD_L))
    {
        TOGGLE(m->modif, MOD_L);
        m->convers = 'S';
    }
}
Esempio n. 10
0
int				print_sign(t_mod *m, va_list ap)
{
	size_t		cnt;
	t_ll		arg;
	char		buf[128];

	arg = get_arg_sign(m, ap);
	if (arg < 0)
	{
		UNSET(m->flag, F_SPACE);
		m->length--;
	}
	if (GET(m->flag, F_PLUS))
		m->length--;
	get_buf(m, arg, buf);
	cnt = display_ui(m, buf);
	return (cnt);
}
Esempio n. 11
0
/* Load the histories for Search and Replace and Execute Command. */
void load_history(void)
{
	char *histname = concatenate(statedir, SEARCH_HISTORY);
	FILE *hisfile = fopen(histname, "rb");

	if (hisfile == NULL) {
		if (errno != ENOENT) {
			/* When reading failed, don't save history when we quit. */
			UNSET(HISTORYLOG);
			history_error(N_("Error reading %s: %s"), histname,
						strerror(errno));
		}
	} else {
		/* Load the three history lists -- first search, then replace,
		 * then execute -- from oldest entry to newest.  Between two
		 * lists there is an empty line. */
		linestruct **history = &search_history;
		char *line = NULL;
		size_t buf_len = 0;
		ssize_t read;

		while ((read = getline(&line, &buf_len, hisfile)) > 0) {
			line[--read] = '\0';
			if (read > 0) {
				/* Encode any embedded NUL as 0x0A. */
				unsunder(line, read);
				update_history(history, line);
			} else if (history == &search_history)
				history = &replace_history;
			else
				history = &execute_history;
		}

		fclose(hisfile);
		free(line);
	}

	/* After reading them in, set the status of the lists to "unchanged". */
	history_changed = FALSE;

	free(histname);
}
Esempio n. 12
0
File: chown.c Progetto: akat1/impala
int
sc_chown(thread_t *t, syscall_result_t *r, chown_args_t *args)
{
   int res=0;
    proc_t *p = t->thr_proc;
    vnode_t *node;
    char pname[PATH_MAX];
    if((res = copyinstr(pname, args->fname, PATH_MAX)))
        return res;

    res = vfs_lookup(p->p_curdir, &node, pname, t, LKP_NORMAL);
    if(res)
        return res;
    vattr_t va;
    va.va_mask=VATTR_ALL;
    if((res = VOP_GETATTR(node, &va)))
        goto err;
    res = -EPERM;
    if(p->p_cred->p_euid != 0 && p->p_cred->p_euid != va.va_uid)
        goto err;
    if(p->p_cred->p_euid != 0)  //tak... póki co nie ma zmian dla nie roota
        goto err;
    va.va_mask = VATTR_UID | VATTR_GID | VATTR_MODE;
    if(args->uid!=-1)
        va.va_uid = args->uid;
    if(args->gid!=-1)
        va.va_gid = args->gid;
    if(p->p_cred->p_euid!=0)   //tymczasowo niemożliwe
        UNSET(va.va_mode, S_ISUID | S_ISGID);
    if((res = VOP_SETATTR(node, &va)))
        goto err;
    vrele(node);    
    return 0;
err:
    vrele(node);
    return res;
}
Esempio n. 13
0
void *daemon_thread(void *arg)
{
    TID_t next_tid = 0;
    TID_t hw_tid   = 0;
    int rv, hw_ret_val, regCount;
    hthread_t junk_tid;
    flag hw_available, hw_done;

    sched_param_t my_priority;
    Hint my_policy;

    // Display the daemon's priority
    hthread_getschedparam(hthread_self(),&my_policy,&my_priority);
    //printf("Daemon priority = %d\n", my_priority.sched_priority);

    // Create a pointer to the Daemon's communication struct with main.
    DaemonComm *dc = (DaemonComm *)arg;

    // Create a buffer for software interpreters to export/import their state to.
    ExportBuffer export_buffer;
    ImportBuffer import_buffer;

    // The software_interpreter_list holds active threads that are being interpreted by
    // the software interpreter.
    TCBNode software_interpreter_list[MAX_SW_THREAD];

    // The cur_tcb and the tcb_index are used to reference TCBs in the software interpreter list.
    TCBNode *cur_tcb;
    TCB *new_tcb;
    int tcb_index;

    // Initialize TCB List
    for (cur_tcb = software_interpreter_list; cur_tcb < software_interpreter_list + MAX_SW_THREAD; cur_tcb++)
    {
        UNSET(cur_tcb->valid);
    }

    // Initialize hardware flags
    SET(hw_available);
    SET(hw_done);


    printf("    ...DAEMON running.\n");
    // The daemon will run forever. Currently we have no clean shutdown mechanism.
    while(1)
    {

        // Process each TCB in the software interpreter list.
        for (cur_tcb = software_interpreter_list; cur_tcb < software_interpreter_list + MAX_SW_THREAD; cur_tcb++)
        {
            // If the TCB is invalid, then skip it.
            if (! ISSET(cur_tcb->valid))
                continue;

            // If a thread is done interpreting, then print its return value and invalidate the TCB.
            if (ISSET(cur_tcb->entry.communication.control.done_interpreting))
            {
                printf("DAEMON: Thread id %u (running in SW) returned %d\n", cur_tcb->entry.tid, cur_tcb->entry.communication.data.return_value);
                UNSET(cur_tcb->valid);
                continue;
            }

            // If the thread is done exporting to hardware, then invalidate the TCB and start
            // the hardware interpretation process.
            if (ISSET(cur_tcb->entry.communication.control.done_exporting))
            {
                // TODO: If a software thread has finished exporting, but in the meantime a
                // a new "run this thread only in hardware" request has come in, we need to copy
                // the thread state from the export buffer *back* into a software thread to make
                // room for the hw->sw migration we're about to do.
                // If there is new bytecode available to execute, then process it.
                if (ISSET(dc->new_code) & ISSET(dc->in_hw))
                {
                    // Kick thread back into SW

                    // Find an invalid TCB.
                    for (tcb_index = 0; tcb_index < MAX_SW_THREAD; tcb_index++)
                    {
                        if (! ISSET(software_interpreter_list[tcb_index].valid))
                            break;
                    }

                    // If an available TCB is found, then tcb_index must be less
                    // then MAX_SW_THREAD.
                    if (tcb_index < MAX_SW_THREAD)
                    {
                        // If an invalid TCB exists, initialize it and start
                        // the software interpreter.

                        // Initialize software_interpreter_list[tcb_index]
                        new_tcb = &software_interpreter_list[tcb_index].entry;

                        new_tcb->tid = cur_tcb->entry.tid;
                        new_tcb->virtualization.base_addr = software_interpreter_list[tcb_index].memory;
                        new_tcb->communication.data.export_buffer_addr = & export_buffer;
                        new_tcb->communication.data.import_buffer_addr = & import_buffer;
                        UNSET(new_tcb->communication.control.done_interpreting);
                        UNSET(new_tcb->communication.control.start_exporting);
                        UNSET(new_tcb->communication.control.done_exporting);

                        SET(software_interpreter_list[tcb_index].valid);

                        // Copy program/state to interpreter memory space
                        for (regCount = 0; regCount < NUMBER_REGISTERS ; regCount++)
                        {
                            import_buffer.register_file[regCount] = export_buffer.register_file[regCount];
                        }
                        memcpy(software_interpreter_list[tcb_index].memory, cur_tcb->memory, export_buffer.register_file[SP]);

                        //start_software_interpreter();
                        rv = hthread_create(&junk_tid, NULL, interpreter_entry_point_import, (void *)&(software_interpreter_list[tcb_index].entry));
                    }
                    else
                    {
                        // If the software_interpreter_list is full, issue an error message.
                        fprintf(stderr, "Preallocated TCB list is full.\n");
                    }


                }
                else
                {
                    // Move the thread into HW

                    // Grab the SW thread's TID
                    hw_tid = cur_tcb->entry.tid;

                    // Migrate state from export buffer into HW interpreter
                    reset_HVM();
                    printf("DAEMON: Migrating thread id %u from SW to HW...",hw_tid);
                    import_state_HVM(&export_buffer, cur_tcb->memory);
                    printf("COMPLETE\n");

                    // Start HW interpreter execution
                    light_LED(hw_tid);
                    UNSET(hw_done);
                    run_HVM();

                    // Invalidate TCB
                    UNSET(cur_tcb->valid);
                }
            }
        }


        // Is the hardware done interpreting
        if (is_HVM_done())
        {
            // Export HVM state and grab return value
            light_LED(0);
            SET(hw_done);
            export_state_HVM();
            wait_export_complete_HVM();
            hw_ret_val = get_HVM_return_value();

            // Display return value
            printf("DAEMON: Thread id %u (running in HW) returned %d\n", hw_tid, hw_ret_val);

            // Check to see if any SW threads exist that can now be run in HW
            for (tcb_index = 0; tcb_index < MAX_SW_THREAD; tcb_index++)
            {
                if (software_interpreter_list[tcb_index].valid)
                    break;
            }

            // If a valid SW thread exists, begin it's export process so that it can be migrated (otherwise, make the HW available again)
            if (tcb_index < MAX_SW_THREAD) {
                SET(software_interpreter_list[tcb_index].entry.communication.control.start_exporting);
            }
            else {
                printf("DAEMON: HW is available for the taking!\n");
                SET(hw_available);
            }
        }


        // If there is new bytecode available to execute, then process it.
        if (ISSET(dc->new_code))
        {
            // Increment the TID counter
            next_tid++;

            // If told to run this thread in HW, check to see if we need to force the HW to be available (migrating a thread from HW to SW)
            if (ISSET(dc->in_hw))
            {
                // Check to see if HW is even available
                if (!ISSET(hw_available) & !ISSET(hw_done))
                {
                    // It's not, so we must make it available
                    // export hardware to software, if needed
                    printf("DAEMON: Migrating thread id %u from HW to SW...", hw_tid);

                    // Stop HVM and export its state
                    light_LED(0);
                    export_state_HVM();

                    //wait_export_complete_HVM(); // This function waits for exported PC to be all F's and this won't be the case in a pre-empted program
                    delay(99999999);  // Use a delay instead to wait for export process to finish

                    printf("COMPLETE\n");

                    // migrate HW state to import buffer (registers now, and program/stack later - just below)
                    migrate_HVM_registers_to_buffer(&import_buffer);

                    // create new SW based on import buffer

                    // Find an invalid TCB.
                    for (tcb_index = 0; tcb_index < MAX_SW_THREAD; tcb_index++)
                    {
                        if (! ISSET(software_interpreter_list[tcb_index].valid))
                            break;
                    }

                    // If an available TCB is found, then tcb_index must be less
                    // then MAX_SW_THREAD.
                    if (tcb_index < MAX_SW_THREAD)
                    {
                        // If an invalid TCB exists, initialize it and start
                        // the software interpreter.

                        // Initialize software_interpreter_list[tcb_index]
                        new_tcb = &software_interpreter_list[tcb_index].entry;

                        new_tcb->tid = hw_tid;
                        new_tcb->virtualization.base_addr = software_interpreter_list[tcb_index].memory;
                        new_tcb->communication.data.export_buffer_addr = & export_buffer;
                        new_tcb->communication.data.import_buffer_addr = & import_buffer;
                        UNSET(new_tcb->communication.control.done_interpreting);
                        UNSET(new_tcb->communication.control.start_exporting);
                        UNSET(new_tcb->communication.control.done_exporting);

                        SET(software_interpreter_list[tcb_index].valid);

                        // Copy program/state to interpreter memory space
                        //memcpy(software_interpreter_list[tcb_index].memory, dc->new_code_address, dc->new_code_size);
                        memcpy(software_interpreter_list[tcb_index].memory, hvm_prog_mem, get_current_SP_HVM());

                        //start_software_interpreter();
                        rv = hthread_create(&junk_tid, NULL, interpreter_entry_point_import, (void *)&(software_interpreter_list[tcb_index].entry));
                    }
                    else
                    {
                        // If the software_interpreter_list is full, issue an error message.
                        fprintf(stderr, "Preallocated TCB list is full.\n");
                    }

                    // Set HW available flag, so the new thread falls through and is created by the code below
                    SET(hw_available);
                }
                else if (!ISSET(hw_available) & ISSET(hw_done))
                {
                    // If its not available, but the thread in HW is complete, then there is no need to migrate the thread...
                    // Just change the availalbility flag for the code below to take care of
                    SET(hw_available);
                }
            }


            // TODO: I don't think we need this else, now.  The dc->in_hw flag just forces a
            // hw -> sw migration, making the hw available to the new thread.
            // If HW available, run the thread in HW
            if ISSET(hw_available)
            {
                // De-asser ready flag
                UNSET(hw_available);

                // Download fresh code
                hw_tid = next_tid;
                printf("DAEMON: Started thread id %u in HW\n", hw_tid);
                load_memory(hvm_prog_mem, dc->new_code_size, dc->new_code_address);

                // Reset and run the interpreter
                reset_HVM();
                light_LED(hw_tid);
                UNSET(hw_done);
                run_HVM();

            }
            // Otherwise run the thread in SW
            else
            {
                // This bytecode will run in software. Therefore it needs
                // to given a TCB in the software interpreter list.

                // Find an invalid TCB.
                for (tcb_index = 0; tcb_index < MAX_SW_THREAD; tcb_index++)
                {
                    if (! ISSET(software_interpreter_list[tcb_index].valid))
                        break;
                }

                // If an available TCB is found, then tcb_index must be less
                // then MAX_SW_THREAD.
                if (tcb_index < MAX_SW_THREAD)
                {
                    // If an invalid TCB exists, initialize it and start
                    // the software interpreter.

                    // Initialize software_interpreter_list[tcb_index]
                    new_tcb = &software_interpreter_list[tcb_index].entry;

                    new_tcb->tid = next_tid;
                    new_tcb->virtualization.base_addr = software_interpreter_list[tcb_index].memory;
                    new_tcb->communication.data.export_buffer_addr = & export_buffer;
                    new_tcb->communication.data.import_buffer_addr = & import_buffer;
                    UNSET(new_tcb->communication.control.done_interpreting);
                    UNSET(new_tcb->communication.control.start_exporting);
                    UNSET(new_tcb->communication.control.done_exporting);

                    SET(software_interpreter_list[tcb_index].valid);
                    memcpy(software_interpreter_list[tcb_index].memory, dc->new_code_address, dc->new_code_size);

                    //start_software_interpreter();
                    printf("DAEMON: Started thread id %u in SW\n", next_tid);
                    rv = hthread_create(&junk_tid, NULL, interpreter_entry_point, (void *)&(software_interpreter_list[tcb_index].entry));
                }
                else
                {
                    // If the software_interpreter_list is full, issue an error message.
                    fprintf(stderr, "Preallocated TCB list is full.\n");
                }
            }

            // Unset the new_code flag
            UNSET(dc->new_code);
        }
Esempio n. 14
0
void setup()
{
	serial_buffer_head = serial_buffer;
	serial_buffer_tail = serial_buffer;
	serial_overflow = false;
	debug_value = 0x1337;
	arch_setup_start();
	enabled_pins = NUM_DIGITAL_PINS;
	for (uint8_t p = 0; p < NUM_DIGITAL_PINS; ++p) {
		pin[p].duty = 255;
		// Reset state is unset, then unset the pin.
		pin[p].state = CTRL_UNSET << 2 | CTRL_RESET;
		UNSET(p);
	}
	pin_events = 0;
	notified_current_fragment = 0;
	current_fragment = notified_current_fragment;
	last_fragment = current_fragment;
	filling = 0;
	// Disable all adcs.
	for (uint8_t a = 0; a < NUM_ANALOG_INPUTS; ++a) {
		for (uint8_t i = 0; i < 2; ++i) {
			adc[a].linked[i] = ~0;
			adc[a].value[i] = 1 << 15;
			adc[a].is_on = false;
		}
	}
	adc_phase = INACTIVE;
	adc_current = ~0;
	adc_next = ~0;
	// Set up communication state.
	command_end = 0;
	had_data = false;
	ping = 0;
	out_busy = 0;
	ff_in = 0;
	ff_out = 0;
	reply_ready = 0;
	adcreply_ready = 0;
	timeout = false;
	timeout_time = 0;
	// Set up homing state.
	homers = 0;
	home_step_time = 0;
	// Set up movement state.
	last_len = 0;
	stopping = -1;
	arch_set_speed(0);
	current_len = 0;
	active_motors = 0;
	move_phase = 0;
	full_phase = 1;
	// Set up led state.
	led_fast = 0;
	led_last = millis();
	led_phase = 0;
	led_pin = ~0;
	stop_pin = ~0;
	probe_pin = ~0;
	spiss_pin = ~0;
	audio = 0;
	audio_motor = 0;
	// Do arch-specific things.  This fills printerid and uuid.
	arch_setup_end();
	// Inform host of reset.
	send_id(CMD_STARTUP);
}
Esempio n. 15
0
File: cut.c Progetto: ris21/yoda
/* Move text from the current linestruct into the cutbuffer.  If
 * copy_text is TRUE, copy the text back into the linestruct afterward.
 * If cut_till_eof is TRUE, move all text from the current cursor
 * position to the end of the file into the cutbuffer. */
void do_cut_text(
#ifndef NANO_TINY
	bool copy_text, bool cut_till_eof, bool undoing
#else
	void
#endif
	)
{
#ifndef NANO_TINY
    linestruct *cb_save = NULL;
	/* The current end of the cutbuffer, before we add text to
	 * it. */
    size_t cb_save_len = 0;
	/* The length of the string at the current end of the cutbuffer,
	 * before we add text to it. */
    bool old_no_newlines = ISSET(NO_NEWLINES);
#endif

    assert(openfile->current != NULL && openfile->current->data != NULL);

    /* If keep_cutbuffer is FALSE and the cutbuffer isn't empty, blow
     * away the text in the cutbuffer. */
    if (!keep_cutbuffer && cutbuffer != NULL) {
	free_filestruct(cutbuffer);
	cutbuffer = NULL;
#ifdef DEBUG
	fprintf(stderr, "Blew away cutbuffer =)\n");
#endif
    }

#ifndef NANO_TINY
    if (copy_text) {
	if (cutbuffer != NULL) {
	    /* If the cutbuffer isn't empty, save where it currently
	     * ends.  This is where we'll add the new text. */
	    cb_save = cutbottom;
	    cb_save_len = strlen(cutbottom->data);
	}

	/* Set NO_NEWLINES to TRUE, so that we don't disturb the last
	 * line of the file when moving text to the cutbuffer. */
	SET(NO_NEWLINES);
    }
#endif

    /* Set keep_cutbuffer to TRUE, so that the text we're going to move
     * into the cutbuffer will be added to the text already in the
     * cutbuffer instead of replacing it. */
    keep_cutbuffer = TRUE;

#ifndef NANO_TINY
    if (cut_till_eof) {
	/* If cut_till_eof is TRUE, move all text up to the end of the
	 * file into the cutbuffer. */
	cut_to_eof();
    } else if (openfile->mark_set) {
	/* If the mark is on, move the marked text to the cutbuffer, and
	 * turn the mark off. */
	cut_marked();
	openfile->mark_set = FALSE;
    } else if (ISSET(CUT_TO_END))
	/* If the CUT_TO_END flag is set, move all text up to the end of
	 * the line into the cutbuffer. */
	cut_to_eol();
    else
#endif
	/* Move the entire line into the cutbuffer. */
	cut_line();

#ifndef NANO_TINY
    if (copy_text) {
	/* Copy the text in the cutbuffer, starting at its saved end if
	 * there is one, back into the linestruct.  This effectively
	 * uncuts the text we just cut without marking the file as
	 * modified. */
	if (cutbuffer != NULL) {
	    if (cb_save != NULL) {
		cb_save->data += cb_save_len;
		copy_from_filestruct(cb_save);
		cb_save->data -= cb_save_len;
	    } else
		copy_from_filestruct(cutbuffer);

	    /* Set the current place we want to where the text from the
	     * cutbuffer ends. */
	    openfile->placewewant = xplustabs();
	}

	/* Set NO_NEWLINES back to what it was before, since we're done
	 * disturbing the text. */
	if (!old_no_newlines)
	    UNSET(NO_NEWLINES);
    } else if (!undoing)
	update_undo(cut_till_eof ? CUT_EOF : CUT);

    /* Leave the text in the cutbuffer, and mark the file as
     * modified. */
    if (!copy_text)
#endif /* !NANO_TINY */
	set_modified();

    /* Update the screen. */
    edit_refresh_needed = TRUE;

#ifndef DISABLE_COLOR
    reset_multis(openfile->current, FALSE);
#endif

#ifdef DEBUG
    dump_filestruct(cutbuffer);
#endif
}
Esempio n. 16
0
/* Parse the rcfile, once it has been opened successfully at rcstream,
 * and close it afterwards.  If syntax_only is TRUE, only allow the file
 * to contain color syntax commands: syntax, color, and icolor. */
void parse_rcfile(FILE *rcstream
#ifdef ENABLE_COLOR
	, bool syntax_only
#endif
	)
{
    char *buf = NULL;
    ssize_t len;
    size_t n;

    while ((len = getline(&buf, &n, rcstream)) > 0) {
	char *ptr, *keyword, *option;
	int set = 0;
	size_t i;

	/* Ignore the newline. */
	if (buf[len - 1] == '\n')
	    buf[len - 1] = '\0';

	lineno++;
	ptr = buf;
	while (isblank(*ptr))
	    ptr++;

	/* If we have a blank line or a comment, skip to the next
	 * line. */
	if (*ptr == '\0' || *ptr == '#')
	    continue;

	/* Otherwise, skip to the next space. */
	keyword = ptr;
	ptr = parse_next_word(ptr);

	/* Try to parse the keyword. */
	if (strcasecmp(keyword, "set") == 0) {
#ifdef ENABLE_COLOR
	    if (syntax_only)
		rcfile_error(
			N_("Command \"%s\" not allowed in included file"),
			keyword);
	    else
#endif
		set = 1;
	} else if (strcasecmp(keyword, "unset") == 0) {
#ifdef ENABLE_COLOR
	    if (syntax_only)
		rcfile_error(
			N_("Command \"%s\" not allowed in included file"),
			keyword);
	    else
#endif
		set = -1;
	}
#ifdef ENABLE_COLOR
	else if (strcasecmp(keyword, "include") == 0) {
	    if (syntax_only)
		rcfile_error(
			N_("Command \"%s\" not allowed in included file"),
			keyword);
	    else
		parse_include(ptr);
	} else if (strcasecmp(keyword, "syntax") == 0) {
	    if (endsyntax != NULL && endcolor == NULL)
		rcfile_error(N_("Syntax \"%s\" has no color commands"),
			endsyntax->desc);
	    parse_syntax(ptr);
	} else if (strcasecmp(keyword, "header") == 0)
	    parse_headers(ptr);
	else if (strcasecmp(keyword, "color") == 0)
	    parse_colors(ptr, FALSE);
	else if (strcasecmp(keyword, "icolor") == 0)
	    parse_colors(ptr, TRUE);
	else if (strcasecmp(keyword, "bind") == 0)
	    parse_keybinding(ptr);
#endif /* ENABLE_COLOR */
	else
	    rcfile_error(N_("Command \"%s\" not understood"), keyword);

	if (set == 0)
	    continue;

	if (*ptr == '\0') {
	    rcfile_error(N_("Missing flag"));
	    continue;
	}

	option = ptr;
	ptr = parse_next_word(ptr);

	for (i = 0; rcopts[i].name != NULL; i++) {
	    if (strcasecmp(option, rcopts[i].name) == 0) {
#ifdef DEBUG
		fprintf(stderr, "parse_rcfile(): name = \"%s\"\n", rcopts[i].name);
#endif
		if (set == 1) {
		    if (rcopts[i].flag != 0)
			/* This option has a flag, so it doesn't take an
			 * argument. */
			SET(rcopts[i].flag);
		    else {
			/* This option doesn't have a flag, so it takes
			 * an argument. */
			if (*ptr == '\0') {
			    rcfile_error(
				N_("Option \"%s\" requires an argument"),
				rcopts[i].name);
			    break;
			}
			option = ptr;
			if (*option == '"')
			    option++;
			ptr = parse_argument(ptr);

			option = mallocstrcpy(NULL, option);
#ifdef DEBUG
			fprintf(stderr, "option = \"%s\"\n", option);
#endif

			/* Make sure option is a valid multibyte
			 * string. */
			if (!is_valid_mbstring(option)) {
			    rcfile_error(
				N_("Option is not a valid multibyte string"));
			    break;
			}

#ifndef DISABLE_OPERATINGDIR
			if (strcasecmp(rcopts[i].name, "operatingdir") == 0)
			    operating_dir = option;
			else
#endif
#ifndef DISABLE_WRAPJUSTIFY
			if (strcasecmp(rcopts[i].name, "fill") == 0) {
			    if (!parse_num(option, &wrap_at)) {
				rcfile_error(
					N_("Requested fill size \"%s\" is invalid"),
					option);
				wrap_at = -CHARS_FROM_EOL;
			    } else
				free(option);
			} else
#endif
#ifndef NANO_TINY
			if (strcasecmp(rcopts[i].name,
				"matchbrackets") == 0) {
			    matchbrackets = option;
			    if (has_blank_mbchars(matchbrackets)) {
				rcfile_error(
					N_("Non-blank characters required"));
				free(matchbrackets);
				matchbrackets = NULL;
			    }
			} else if (strcasecmp(rcopts[i].name,
				"whitespace") == 0) {
			    whitespace = option;
			    if (mbstrlen(whitespace) != 2 ||
				strlenpt(whitespace) != 2) {
				rcfile_error(
					N_("Two single-column characters required"));
				free(whitespace);
				whitespace = NULL;
			    } else {
				whitespace_len[0] =
					parse_mbchar(whitespace, NULL,
					NULL);
				whitespace_len[1] =
					parse_mbchar(whitespace +
					whitespace_len[0], NULL, NULL);
			    }
			} else
#endif
#ifndef DISABLE_JUSTIFY
			if (strcasecmp(rcopts[i].name, "punct") == 0) {
			    punct = option;
			    if (has_blank_mbchars(punct)) {
				rcfile_error(
					N_("Non-blank characters required"));
				free(punct);
				punct = NULL;
			    }
			} else if (strcasecmp(rcopts[i].name,
				"brackets") == 0) {
			    brackets = option;
			    if (has_blank_mbchars(brackets)) {
				rcfile_error(
					N_("Non-blank characters required"));
				free(brackets);
				brackets = NULL;
			    }
			} else if (strcasecmp(rcopts[i].name,
				"quotestr") == 0)
			    quotestr = option;
			else
#endif
#ifndef NANO_TINY
			if (strcasecmp(rcopts[i].name,
				"backupdir") == 0)
			    backup_dir = option;
			else
#endif
#ifndef DISABLE_SPELLER
			if (strcasecmp(rcopts[i].name, "speller") == 0)
			    alt_speller = option;
			else
#endif
			if (strcasecmp(rcopts[i].name,
				"tabsize") == 0) {
			    if (!parse_num(option, &tabsize) ||
				tabsize <= 0) {
				rcfile_error(
					N_("Requested tab size \"%s\" is invalid"),
					option);
				tabsize = -1;
			    } else
				free(option);
			} else
			    assert(FALSE);
		    }
#ifdef DEBUG
		    fprintf(stderr, "flag = %ld\n", rcopts[i].flag);
#endif
		} else if (rcopts[i].flag != 0)
		    UNSET(rcopts[i].flag);
		else
		    rcfile_error(N_("Cannot unset flag \"%s\""),
			rcopts[i].name);
		break;
	    }
	}
	if (rcopts[i].name == NULL)
	    rcfile_error(N_("Unknown flag \"%s\""), option);
    }

#ifdef ENABLE_COLOR
    if (endsyntax != NULL && endcolor == NULL)
	rcfile_error(N_("Syntax \"%s\" has no color commands"),
		endsyntax->desc);
#endif

    free(buf);
    fclose(rcstream);
    lineno = 0;

    check_vitals_mapped();
    return;
}
Esempio n. 17
0
File: browser.c Progetto: ris21/yoda
/* Our main file browser function.  path is the tilde-expanded path we
 * start browsing from. */
char *do_browser(char *path, DIR *dir)
{
    char *retval = NULL;
    int kbinput;
    bool old_const_update = ISSET(CONST_UPDATE);
    char *prev_dir = NULL;
	/* The directory we were in before backing up to "..". */
    char *ans = NULL;
	/* The last answer the user typed at the statusbar prompt. */
    size_t old_selected;
	/* The selected file we had before the current selected file. */
    functionptrtype func;
	/* The function of the key the user typed in. */

    curs_set(0);
    blank_statusbar();
    bottombars(MBROWSER);
    wnoutrefresh(bottomwin);

    UNSET(CONST_UPDATE);

    ans = mallocstrcpy(NULL, "");

  change_browser_directory:
	/* We go here after we select a new directory. */

    /* Start with no key pressed. */
    kbinput = ERR;

    path = mallocstrassn(path, get_full_path(path));

    /* Save the current path in order to be used later. */
    path_save = path;

    assert(path != NULL && path[strlen(path) - 1] == '/');

    /* Get the file list, and set longest and width in the process. */
    browser_init(path, dir);

    assert(filelist != NULL);

    /* Sort the file list. */
    qsort(filelist, filelist_len, sizeof(char *), diralphasort);

    /* If prev_dir isn't NULL, select the directory saved in it, and
     * then blow it away. */
    if (prev_dir != NULL) {
	browser_select_dirname(prev_dir);

	free(prev_dir);
	prev_dir = NULL;
    /* Otherwise, select the first file or directory in the list. */
    } else
	selected = 0;

    old_selected = (size_t)-1;

    titlebar(path);

    while (TRUE) {
	struct stat st;
	int i;
	size_t fileline = selected / width;
		/* The line number the selected file is on. */
	char *new_path;
		/* The path we switch to at the "Go to Directory"
		 * prompt. */

	/* Display the file list if we don't have a key, or if the
	 * selected file has changed, and set width in the process. */
	if (kbinput == ERR || old_selected != selected)
	    browser_refresh();

	old_selected = selected;

	kbinput = get_kbinput(edit);

#ifndef NANO_TINY
	if (kbinput == KEY_WINCH) {
	    kbinput = ERR;
	    curs_set(0);
	    continue;
	}
#endif

#ifndef DISABLE_MOUSE
	if (kbinput == KEY_MOUSE) {
	    int mouse_x, mouse_y;

	    /* We can click on the edit window to select a
	     * filename. */
	    if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 &&
		wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
		/* longest is the width of each column.  There
		 * are two spaces between each column. */
		selected = (fileline / editwinrows) *
				(editwinrows * width) + (mouse_y *
				width) + (mouse_x / (longest + 2));

		/* If they clicked beyond the end of a row,
		 * select the last filename in that row. */
		if (mouse_x > width * (longest + 2))
		    selected--;

		/* If we're off the screen, select the last filename. */
		if (selected > filelist_len - 1)
		    selected = filelist_len - 1;

		/* If we selected the same filename as last time,
		 * put back the Enter key so that it's read in. */
		if (old_selected == selected)
		    unget_kbinput(sc_seq_or(do_enter_void, 0), FALSE, FALSE);
	    }
	}
#endif /* !DISABLE_MOUSE */

	func = parse_browser_input(&kbinput);

	if (func == total_refresh) {
	    total_redraw();
	} else if (func == do_help_void) {
#ifndef DISABLE_HELP
	    do_help_void();
	    /* Perhaps the window dimensions have changed. */
	    browser_refresh();
	    curs_set(0);
#else
	    nano_disabled_msg();
#endif
	} else if (func == do_search) {
	    /* Search for a filename. */
	    curs_set(1);
	    do_filesearch();
	    curs_set(0);
	} else if (func == do_research) {
	    /* Search for another filename. */
	    do_fileresearch();
	} else if (func == do_page_up) {
	    if (selected >= (editwinrows + fileline % editwinrows) * width)
		selected -= (editwinrows + fileline % editwinrows) * width;
	    else
		selected = 0;
	} else if (func == do_page_down) {
	    selected += (editwinrows - fileline % editwinrows) * width;
	    if (selected > filelist_len - 1)
		selected = filelist_len - 1;
	} else if (func == do_first_file) {
	    selected = 0;
	} else if (func == do_last_file) {
	    selected = filelist_len - 1;
	} else if (func == goto_dir_void) {
	    /* Go to a specific directory. */
	    curs_set(1);
	    i = do_prompt(TRUE,
#ifndef DISABLE_TABCOMP
			FALSE,
#endif
			MGOTODIR, ans,
#ifndef DISABLE_HISTORIES
			NULL,
#endif
			/* TRANSLATORS: This is a prompt. */
			browser_refresh, _("Go To Directory"));

	    curs_set(0);
	    bottombars(MBROWSER);

	    /* If the directory begins with a newline (i.e. an
	     * encoded null), treat it as though it's blank. */
	    if (i < 0 || *answer == '\n') {
		/* We canceled.  Indicate that on the statusbar, and
		* blank out ans, since we're done with it. */
		statusbar(_("Cancelled"));
		ans = mallocstrcpy(ans, "");
		continue;
	    } else if (i != 0) {
		/* Put back the "Go to Directory" key and save
		 * answer in ans, so that the file list is displayed
		 * again, the prompt is displayed again, and what we
		 * typed before at the prompt is displayed again. */
		unget_kbinput(sc_seq_or(do_gotolinecolumn_void, 0), FALSE, FALSE);
		ans = mallocstrcpy(ans, answer);
		continue;
	    }

	    /* We have a directory.  Blank out ans, since we're done
	     * with it. */
	    ans = mallocstrcpy(ans, "");

	    /* Convert newlines to nulls, just before we go to the
	     * directory. */
	    sunder(answer);
	    align(&answer);

	    new_path = real_dir_from_tilde(answer);

	    if (new_path[0] != '/') {
		new_path = charealloc(new_path, strlen(path) +
				strlen(answer) + 1);
		sprintf(new_path, "%s%s", path, answer);
	    }

#ifndef DISABLE_OPERATINGDIR
	    if (check_operating_dir(new_path, FALSE)) {
		statusbar(_("Can't go outside of %s in restricted mode"),
				operating_dir);
		free(new_path);
		continue;
	    }
#endif

	    dir = opendir(new_path);
	    if (dir == NULL) {
		/* We can't open this directory for some reason.
		* Complain. */
		statusbar(_("Error reading %s: %s"), answer,
				strerror(errno));
		beep();
		free(new_path);
		continue;
	    }

	    /* Start over again with the new path value. */
	    free(path);
	    path = new_path;
	    goto change_browser_directory;
	} else if (func == do_up_void) {
	    if (selected >= width)
		selected -= width;
	} else if (func == do_down_void) {
	    if (selected + width <= filelist_len - 1)
		selected += width;
	} else if (func == do_left) {
	    if (selected > 0)
		selected--;
	} else if (func == do_right) {
	    if (selected < filelist_len - 1)
		selected++;
	} else if (func == do_enter_void) {
	    /* We can't move up from "/". */
	    if (strcmp(filelist[selected], "/..") == 0) {
		statusbar(_("Can't move up a directory"));
		beep();
		continue;
	    }

#ifndef DISABLE_OPERATINGDIR
	    /* Note: The selected file can be outside the operating
	     * directory if it's ".." or if it's a symlink to a
	     * directory outside the operating directory. */
	    if (check_operating_dir(filelist[selected], FALSE)) {
		statusbar(_("Can't go outside of %s in restricted mode"),
				operating_dir);
		beep();
		continue;
	    }
#endif

	    if (stat(filelist[selected], &st) == -1) {
		/* We can't open this file for some reason.
		 * Complain. */
		 statusbar(_("Error reading %s: %s"),
				filelist[selected], strerror(errno));
		 beep();
		 continue;
	    }

	    if (!S_ISDIR(st.st_mode)) {
		/* We've successfully opened a file, we're done, so
		 * get out. */
		retval = mallocstrcpy(NULL, filelist[selected]);
		break;
	    } else if (strcmp(tail(filelist[selected]), "..") == 0)
		/* We've successfully opened the parent directory,
		 * save the current directory in prev_dir, so that
		 * we can easily return to it by hitting Enter. */
		prev_dir = mallocstrcpy(NULL, striponedir(filelist[selected]));

	    dir = opendir(filelist[selected]);
	    if (dir == NULL) {
		/* We can't open this directory for some reason.
		 * Complain. */
		statusbar(_("Error reading %s: %s"),
				filelist[selected], strerror(errno));
		beep();
		continue;
	    }

	    path = mallocstrcpy(path, filelist[selected]);

	    /* Start over again with the new path value. */
	    goto change_browser_directory;
	} else if (func == do_exit) {
	    /* Exit from the file browser. */
	    break;
	}
    }
    titlebar(NULL);
    edit_refresh();
    curs_set(1);
    if (old_const_update)
	SET(CONST_UPDATE);

    free(path);
    free(ans);

    free_chararray(filelist, filelist_len);
    filelist = NULL;
    filelist_len = 0;

    return retval;
}
Esempio n. 18
0
/* Our main help-viewer function. */
void do_help(void)
{
    int kbinput = ERR;
    bool old_no_help = ISSET(NO_HELP);
    size_t line = 0;
	/* The line number in help_text of the first displayed help
	 * line.  This variable is zero-based. */
    size_t last_line = 0;
	/* The line number in help_text of the last help line.  This
	 * variable is zero-based. */
    int oldmenu = currmenu;
	/* The menu we were called from. */
    const char *ptr;
	/* The current line of the help text. */
    size_t old_line = (size_t)-1;
	/* The line we were on before the current line. */
    functionptrtype func;
	/* The function of the key the user typed in. */

    /* Don't show a cursor in the help screen. */
    curs_set(0);
    blank_edit();
    blank_statusbar();

    /* Set help_text as the string to display. */
    help_init();

    assert(help_text != NULL);

    if (ISSET(NO_HELP)) {
	/* Make sure that the help screen's shortcut list will actually
	 * be displayed. */
	UNSET(NO_HELP);
	window_init();
    }

    bottombars(MHELP);
    wnoutrefresh(bottomwin);

    while (TRUE) {
	size_t i;

	ptr = help_text;

	/* Find the line number of the last line of the help text. */
	for (last_line = 0; *ptr != '\0'; last_line++) {
	    ptr += help_line_len(ptr);
	    if (*ptr == '\n')
		ptr++;
	}

	if (last_line > 0)
	    last_line--;

	/* Redisplay if the text was scrolled or an invalid key was pressed. */
	if (line != old_line || kbinput == ERR) {
	    blank_edit();

	    ptr = help_text;

	    /* Advance in the text to the first line to be displayed. */
	    for (i = 0; i < line; i++) {
		ptr += help_line_len(ptr);
		if (*ptr == '\n')
		    ptr++;
	    }

	    /* Now display as many lines as the window will hold. */
	    for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
		size_t j = help_line_len(ptr);

		mvwaddnstr(edit, i, 0, ptr, j);
		ptr += j;
		if (*ptr == '\n')
		    ptr++;
	    }
	}

	wnoutrefresh(edit);

	old_line = line;

	lastmessage = HUSH;

	kbinput = get_kbinput(edit);

#ifndef NANO_TINY
	if (kbinput == KEY_WINCH) {
	    kbinput = ERR;
	    continue;    /* Redraw the screen. */
	}
#endif

#ifndef DISABLE_MOUSE
	if (kbinput == KEY_MOUSE) {
	    int mouse_x, mouse_y;
	    get_mouseinput(&mouse_x, &mouse_y, TRUE);
	    continue;    /* Redraw the screen. */
	}
#endif

	func = parse_help_input(&kbinput);

	if (func == total_refresh) {
	    total_redraw();
	} else if (func == do_up_void) {
	    if (line > 0)
		line--;
	} else if (func == do_down_void) {
	    if (line + (editwinrows - 1) < last_line)
		line++;
	} else if (func == do_page_up) {
	    if (line > editwinrows - 2)
		line -= editwinrows - 2;
	    else
		line = 0;
	} else if (func == do_page_down) {
	    if (line + (editwinrows - 1) < last_line)
		line += editwinrows - 2;
	} else if (func == do_first_line) {
	    line = 0;
	} else if (func == do_last_line) {
	    if (line + (editwinrows - 1) < last_line)
		line = last_line - (editwinrows - 1);
	} else if (func == do_exit) {
	    /* Exit from the help viewer. */
	    break;
	} else
	    unbound_key(kbinput);
    }

    if (old_no_help) {
	blank_bottombars();
	wnoutrefresh(bottomwin);
	currmenu = oldmenu;
	SET(NO_HELP);
	window_init();
    } else
	bottombars(oldmenu);

#ifndef DISABLE_BROWSER
    if (oldmenu == MBROWSER || oldmenu == MWHEREISFILE || oldmenu == MGOTODIR)
	browser_refresh();
    else
#endif
	edit_refresh();

    /* We're exiting from the help screen. */
    free(help_text);
}
Esempio n. 19
0
/* Allocate space for the help text for the current menu, and concatenate
 * the different pieces of text into it. */
void help_init(void)
{
    size_t allocsize = 0;
	/* Space needed for help_text. */
    const char *htx[3];
	/* Untranslated help introduction.  We break it up into three chunks
	 * in case the full string is too long for the compiler to handle. */
    char *ptr;
    const subnfunc *f;
    const sc *s;

#ifndef NANO_TINY
    bool old_whitespace = ISSET(WHITESPACE_DISPLAY);

    UNSET(WHITESPACE_DISPLAY);
#endif

    /* First, set up the initial help text for the current function. */
    if (currmenu == MWHEREIS || currmenu == MREPLACE || currmenu == MREPLACEWITH) {
	htx[0] = N_("Search Command Help Text\n\n "
		"Enter the words or characters you would like to "
		"search for, and then press Enter.  If there is a "
		"match for the text you entered, the screen will be "
		"updated to the location of the nearest match for the "
		"search string.\n\n The previous search string will be "
		"shown in brackets after the search prompt.  Hitting "
		"Enter without entering any text will perform the "
		"previous search.  ");
	htx[1] = N_("If you have selected text with the mark and then "
		"search to replace, only matches in the selected text "
		"will be replaced.\n\n The following function keys are "
		"available in Search mode:\n\n");
	htx[2] = NULL;
    } else if (currmenu == MGOTOLINE) {
	htx[0] = N_("Go To Line Help Text\n\n "
		"Enter the line number that you wish to go to and hit "
		"Enter.  If there are fewer lines of text than the "
		"number you entered, you will be brought to the last "
		"line of the file.\n\n The following function keys are "
		"available in Go To Line mode:\n\n");
	htx[1] = NULL;
	htx[2] = NULL;
    } else if (currmenu == MINSERTFILE) {
	htx[0] = N_("Insert File Help Text\n\n "
		"Type in the name of a file to be inserted into the "
		"current file buffer at the current cursor "
		"location.\n\n If you have compiled nano with multiple "
		"file buffer support, and enable multiple file buffers "
		"with the -F or --multibuffer command line flags, the "
		"Meta-F toggle, or a nanorc file, inserting a file "
		"will cause it to be loaded into a separate buffer "
		"(use Meta-< and > to switch between file buffers).  ");
	htx[1] = N_("If you need another blank buffer, do not enter "
		"any filename, or type in a nonexistent filename at "
		"the prompt and press Enter.\n\n The following "
		"function keys are available in Insert File mode:\n\n");
	htx[2] = NULL;
    } else if (currmenu == MWRITEFILE) {
	htx[0] = N_("Write File Help Text\n\n "
		"Type the name that you wish to save the current file "
		"as and press Enter to save the file.\n\n If you have "
		"selected text with the mark, you will be prompted to "
		"save only the selected portion to a separate file.  To "
		"reduce the chance of overwriting the current file with "
		"just a portion of it, the current filename is not the "
		"default in this mode.\n\n The following function keys "
		"are available in Write File mode:\n\n");
	htx[1] = NULL;
	htx[2] = NULL;
    }
#ifndef DISABLE_BROWSER
    else if (currmenu == MBROWSER) {
	htx[0] = N_("File Browser Help Text\n\n "
		"The file browser is used to visually browse the "
		"directory structure to select a file for reading "
		"or writing.  You may use the arrow keys or Page Up/"
		"Down to browse through the files, and S or Enter to "
		"choose the selected file or enter the selected "
		"directory.  To move up one level, select the "
		"directory called \"..\" at the top of the file "
		"list.\n\n The following function keys are available "
		"in the file browser:\n\n");
	htx[1] = NULL;
	htx[2] = NULL;
    } else if (currmenu == MWHEREISFILE) {
	htx[0] = N_("Browser Search Command Help Text\n\n "
		"Enter the words or characters you would like to "
		"search for, and then press Enter.  If there is a "
		"match for the text you entered, the screen will be "
		"updated to the location of the nearest match for the "
		"search string.\n\n The previous search string will be "
		"shown in brackets after the search prompt.  Hitting "
		"Enter without entering any text will perform the "
		"previous search.\n\n");
	htx[1] = N_(" The following function keys are available in "
		"Browser Search mode:\n\n");
	htx[2] = NULL;
    } else if (currmenu == MGOTODIR) {
	htx[0] = N_("Browser Go To Directory Help Text\n\n "
		"Enter the name of the directory you would like to "
		"browse to.\n\n If tab completion has not been "
		"disabled, you can use the Tab key to (attempt to) "
		"automatically complete the directory name.\n\n The "
		"following function keys are available in Browser Go "
		"To Directory mode:\n\n");
	htx[1] = NULL;
	htx[2] = NULL;
    }
#endif /* !DISABLE_BROWSER */
#ifndef DISABLE_SPELLER
    else if (currmenu == MSPELL) {
	htx[0] = N_("Spell Check Help Text\n\n "
		"The spell checker checks the spelling of all text in "
		"the current file.  When an unknown word is "
		"encountered, it is highlighted and a replacement can "
		"be edited.  It will then prompt to replace every "
		"instance of the given misspelled word in the current "
		"file, or, if you have selected text with the mark, in "
		"the selected text.\n\n The following function keys "
		"are available in Spell Check mode:\n\n");
	htx[1] = NULL;
	htx[2] = NULL;
    }
#endif /* !DISABLE_SPELLER */
#ifndef NANO_TINY
    else if (currmenu == MEXTCMD) {
	htx[0] = N_("Execute Command Help Text\n\n "
		"This mode allows you to insert the output of a "
		"command run by the shell into the current buffer (or "
		"a new buffer in multiple file buffer mode).  If you "
		"need another blank buffer, do not enter any "
		"command.\n\n The following function keys are "
		"available in Execute Command mode:\n\n");
	htx[1] = NULL;
	htx[2] = NULL;
    }
#endif /* !NANO_TINY */
    else {
	/* Default to the main help list. */
	htx[0] = N_("Main nano help text\n\n "
		"The nano editor is designed to emulate the "
		"functionality and ease-of-use of the UW Pico text "
		"editor.  There are four main sections of the editor.  "
		"The top line shows the program version, the current "
		"filename being edited, and whether or not the file "
		"has been modified.  Next is the main editor window "
		"showing the file being edited.  The status line is "
		"the third line from the bottom and shows important "
		"messages.  ");
	htx[1] = N_("The bottom two lines show the most commonly used "
		"shortcuts in the editor.\n\n Shortcuts are written as "
		"follows: Control-key sequences are notated with a '^' "
		"and can be entered either by using the Ctrl key or "
		"pressing the Esc key twice.  Meta-key sequences are "
		"notated with 'M-' and can be entered using either the "
		"Alt, Cmd, or Esc key, depending on your keyboard setup.  ");
	htx[2] = N_("Also, pressing Esc twice and then typing a "
		"three-digit decimal number from 000 to 255 will enter "
		"the character with the corresponding value.  The "
		"following keystrokes are available in the main editor "
		"window.  Alternative keys are shown in "
		"parentheses:\n\n");
    }

    htx[0] = _(htx[0]);
    if (htx[1] != NULL)
	htx[1] = _(htx[1]);
    if (htx[2] != NULL)
	htx[2] = _(htx[2]);

    allocsize += strlen(htx[0]);
    if (htx[1] != NULL)
	allocsize += strlen(htx[1]);
    if (htx[2] != NULL)
	allocsize += strlen(htx[2]);

    /* Calculate the length of the shortcut help text.  Each entry has
     * one or two keys, which fill 16 columns, plus translated text,
     * plus one or two \n's. */
    for (f = allfuncs; f != NULL; f = f->next)
	if (f->menus & currmenu)
	    allocsize += (16 * mb_cur_max()) + strlen(f->help) + 2;

#ifndef NANO_TINY
    /* If we're on the main list, we also count the toggle help text.
     * Each entry has "M-%c\t\t", five chars which fill 16 columns,
     * plus a space, plus translated text, plus one or two '\n's. */
    if (currmenu == MMAIN) {
	size_t endis_len = strlen(_("enable/disable"));

	for (s = sclist; s != NULL; s = s->next)
	    if (s->scfunc == do_toggle_void)
		allocsize += strlen(_(flagtostr(s->toggle))) + endis_len + 8;
    }
#endif

    /* Allocate space for the help text. */
    help_text = charalloc(allocsize + 1);

    /* Now add the text we want. */
    strcpy(help_text, htx[0]);
    if (htx[1] != NULL)
	strcat(help_text, htx[1]);
    if (htx[2] != NULL)
	strcat(help_text, htx[2]);

    ptr = help_text + strlen(help_text);

    /* Remember this end-of-introduction, start-of-shortcuts. */
    end_of_intro = ptr;

    /* Now add our shortcut info. */
    for (f = allfuncs; f != NULL; f = f->next) {
	int scsfound = 0;

	if ((f->menus & currmenu) == 0)
	    continue;

	/* Let's simply show the first two shortcuts from the list. */
	for (s = sclist; s != NULL; s = s->next) {

	    if ((s->menus & currmenu) == 0)
		continue;

	    if (s->scfunc == f->scfunc) {
		scsfound++;
		/* Make the first column narrower (6) than the second (10),
		 * but allow it to spill into the second, for "M-Space". */
		if (scsfound == 1) {
		    sprintf(ptr, "%s              ", s->keystr);
		    /* Unicode arrows take three bytes instead of one. */
		    if (s->keystr[1] == '\xE2')
			ptr += 8;
		    else
			ptr += 6;
		} else {
		    ptr += sprintf(ptr, "(%s)\t", s->keystr);
		    break;
		}
	    }
	}

	if (scsfound == 0)
	    ptr += sprintf(ptr, "\t\t");
	else if (scsfound == 1)
	    ptr += 10;

	/* The shortcut's help text. */
	ptr += sprintf(ptr, "%s\n", _(f->help));

	if (f->blank_after)
	    ptr += sprintf(ptr, "\n");
    }

#ifndef NANO_TINY
    /* And the toggles... */
    if (currmenu == MMAIN) {
	int maximum = 0, counter = 0;

	/* First see how many toggles there are. */
	for (s = sclist; s != NULL; s = s->next)
	    maximum = (s->toggle && s->ordinal > maximum) ? s->ordinal : maximum;

	/* Now show them in the original order. */
	while (counter < maximum) {
	    counter++;
	    for (s = sclist; s != NULL; s = s->next)
		if (s->toggle && s->ordinal == counter) {
		    ptr += sprintf(ptr, "%s\t\t%s %s\n", (s->menus == MMAIN ? s->keystr : ""),
				_(flagtostr(s->toggle)), _("enable/disable"));
		    if (s->toggle == NO_COLOR_SYNTAX || s->toggle == TABS_TO_SPACES)
			ptr += sprintf(ptr, "\n");
		    break;
		}
	}
    }

    if (old_whitespace)
	SET(WHITESPACE_DISPLAY);
#endif /* !NANO_TINY */

    /* If all went well, we didn't overwrite the allocated space. */
    assert(strlen(help_text) <= allocsize + 1);
}
Esempio n. 20
0
void received(){
	UNSET(RECEIVED);
	bufferCursor = 0;
}
Esempio n. 21
0
/* Our main file browser function.  path is the tilde-expanded path we
 * start browsing from. */
std::string do_browser(std::string path, DIR *dir)
{
	std::string retval;
	bool old_const_update = ISSET(CONST_UPDATE);
	std::string prev_dir;
	/* The directory we were in before backing up to "..". */
	std::string ans;
	/* The last answer the user typed at the statusbar prompt. */
	size_t old_selected;
	/* The selected file we had before the current selected file. */

	curs_set(0);
	blank_statusbar();
	bottombars(MBROWSER);
	wnoutrefresh(bottomwin);

	UNSET(CONST_UPDATE);

change_browser_directory:
	/* We go here after we select a new directory. */

	path = get_full_path(path);

	assert(path.length() > 0 && path.back() == '/');

	/* Get the file list, and set longest and width in the process. */
	browser_init(path, dir);

	/* Sort the file list. */
	std::sort(filelist.begin(), filelist.end(), sort_directories);

	/* If prev_dir isn't empty, select the directory saved in it, and then blow it away. */
	if (prev_dir != "") {
		browser_select_filename(prev_dir);

		prev_dir = "";
		/* Otherwise, select the first file or directory in the list. */
	} else {
		selected = 0;
	}

	old_selected = (size_t)-1;

	titlebar(path);

	Key *kbinput = nullptr;

	while (true) {
		struct stat st;
		size_t fileline = selected / width;
		/* The line number the selected file is on. */
		std::string new_path;
		/* The path we switch to at the "Go to Directory" prompt. */

		if (kbinput) {
			delete kbinput;
			kbinput = nullptr;
		}

		/* Display the file list if we don't have a key, or if the
		 * selected file has changed, and set width in the process. */
		if (old_selected != selected) {
			browser_refresh();
		}

		old_selected = selected;

		// Deal with the keyboard input
		kbinput = new Key(get_kbinput(edit));

		auto func = func_from_key(*kbinput);

		if (func == total_refresh) {
			total_redraw();
		} else if (func == do_help_void) {
			do_help_void();
			curs_set(0);
			/* Search for a filename. */
		} else if (func == do_search) {
			curs_set(1);
			do_filesearch();
			curs_set(0);
			/* Search for another filename. */
		} else if (func == do_research) {
			do_fileresearch();
		} else if (func == do_page_up) {
			if (selected >= (editwinrows + fileline % editwinrows) * width) {
				selected -= (editwinrows + fileline % editwinrows) * width;
			} else {
				selected = 0;
			}
		} else if (func == do_page_down) {
			selected += (editwinrows - fileline % editwinrows) * width;
			if (selected > filelist.size() - 1) {
				selected = filelist.size() - 1;
			}
		} else if (func == do_first_file) {
			selected = 0;
		} else if (func == do_last_file) {
			selected = filelist.size() - 1;
		} else if (func == goto_dir_void) {
			/* Go to a specific directory. */
			curs_set(1);

			std::shared_ptr<Key> key;
			PromptResult i = do_prompt(true,
			              false,
			              MGOTODIR, key, ans.c_str(),
			              NULL,
			              browser_refresh, _("Go To Directory"));

			curs_set(0);
			bottombars(MBROWSER);

			/* If the directory begins with a newline (i.e. an
			 * encoded null), treat it as though it's blank. */
			if (i == PROMPT_ABORTED || i == PROMPT_BLANK_STRING || answer.front() == '\n') {
				/* We canceled.  Indicate that on the statusbar, and
				 * blank out ans, since we're done with it. */
				statusbar(_("Cancelled"));
				ans = "";
				func = nullptr;
				continue;
			} else if (i != PROMPT_ENTER_PRESSED) {
				/* Put back the "Go to Directory" key and save
				 * answer in ans, so that the file list is displayed
				 * again, the prompt is displayed again, and what we
				 * typed before at the prompt is displayed again. */
				ans = answer;
				func = goto_dir_void;
				continue;
			}

			/* We have a directory.  Blank out ans, since we're done with it. */
			ans = "";

			/* Convert newlines to nulls, just before we go to the directory. */
			sunder(answer);

			new_path = real_dir_from_tilde(answer);

			if (new_path == "") {
				new_path = path + answer;
			}

			dir = opendir(new_path);
			if (dir == NULL) {
				/* We can't open this directory for some reason. Complain. */
				statusbar(_("Error reading %s: %s"), answer.c_str(), strerror(errno));
				beep();
				func = nullptr;
				continue;
			}

			/* Start over again with the new path value. */
			path = new_path;
			goto change_browser_directory;
		} else if (func == do_up_void) {
			if (selected >= width) {
				selected -= width;
			}
		} else if (func == do_left) {
			if (selected > 0) {
				selected--;
			}
		} else if (func == do_down_void) {
			if (selected + width <= filelist.size() - 1) {
				selected += width;
			}
		} else if (func == do_right) {
			if (selected < filelist.size() - 1) {
				selected++;
			}
		} else if (func == do_enter_void) {
			/* We can't move up from "/". */
			if (filelist[selected] == "/..") {
				statusbar(_("Can't move up a directory"));
				beep();
				func = nullptr;
				continue;
			}

			if (stat(filelist[selected], &st) == -1) {
				/* We can't open this file for some reason. Complain. */
				statusbar(_("Error reading %s: %s"), filelist[selected].c_str(), strerror(errno));
				beep();
				func = nullptr;
				continue;
			}

			if (!S_ISDIR(st.st_mode)) {
				/* We've successfully opened a file, we're done, so get out. */
				retval = filelist[selected];
				func = nullptr;
				break;
			} else if (tail(filelist[selected]) == "..") {
				/* We've successfully opened the parent directory,
				 * save the current directory in prev_dir, so that
				  * we can easily return to it by hitting Enter. */
				prev_dir = striponedir(filelist[selected]);
			}

			dir = opendir(filelist[selected].c_str());
			if (dir == NULL) {
				/* We can't open this directory for some reason. Complain. */
				statusbar(_("Error reading %s: %s"), filelist[selected].c_str(), strerror(errno));
				beep();
				func = nullptr;
				continue;
			}

			path = filelist[selected];

			/* Start over again with the new path value. */
			goto change_browser_directory;
		} else if (func == do_exit) {
			/* Exit from the file browser. */
			break;
		}
		func = nullptr;
	}
	if (kbinput) {
		delete kbinput;
	}
	titlebar(NULL);
	edit_refresh();
	curs_set(1);
	if (old_const_update) {
		SET(CONST_UPDATE);
	}

	filelist.clear();

	return retval;
}
Esempio n. 22
0
/* Load the recorded cursor positions for files that were edited. */
void load_poshistory(void)
{
	FILE *hisfile = fopen(poshistname, "rb");

	if (hisfile == NULL) {
		if (errno != ENOENT) {
			/* When reading failed, don't save history when we quit. */
			UNSET(POSITIONLOG);
			history_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
		}
	} else {
		char *line = NULL, *lineptr, *xptr;
		size_t buf_len = 0;
		ssize_t read, count = 0;
		poshiststruct *record_ptr = NULL, *newrecord;

		/* Read and parse each line, and store the extracted data. */
		while ((read = getline(&line, &buf_len, hisfile)) > 5) {
			/* Decode nulls as embedded newlines. */
			unsunder(line, read);

			/* Find where the x index and line number are in the line. */
			xptr = revstrstr(line, " ", line + read - 3);
			if (xptr == NULL)
				continue;
			lineptr = revstrstr(line, " ", xptr - 2);
			if (lineptr == NULL)
				continue;

			/* Now separate the three elements of the line. */
			*(xptr++) = '\0';
			*(lineptr++) = '\0';

			/* Create a new position record. */
			newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
			newrecord->filename = mallocstrcpy(NULL, line);
			newrecord->lineno = atoi(lineptr);
			newrecord->xno = atoi(xptr);
			newrecord->next = NULL;

			/* Add the record to the list. */
			if (position_history == NULL)
				position_history = newrecord;
			else
				record_ptr->next = newrecord;

			record_ptr = newrecord;

			/* Impose a limit, so the file will not grow indefinitely. */
			if (++count > 200) {
				poshiststruct *drop_record = position_history;

				position_history = position_history->next;

				free(drop_record->filename);
				free(drop_record);
			}
		}
		fclose(hisfile);
		free(line);

		stat(poshistname, &stat_of_positions_file);
	}
}