Exemple #1
0
/*
 * Print a formatted colour message at the bottom of the screen, wait a while
 */
void
wait_message(
	unsigned int sdelay,
	const char *fmt,
	...)
{
	va_list ap;

	va_start(ap, fmt);

	clear_message();
#ifdef HAVE_COLOR
	fcol(tinrc.col_message);
#endif /* HAVE_COLOR */

	vsnprintf(mesg, sizeof(mesg), fmt, ap);
	my_fputs(mesg, stdout);

#ifdef HAVE_COLOR
	fcol(tinrc.col_normal);
#endif /* HAVE_COLOR */
	cursoron();
	my_flush();

	(void) sleep(sdelay);
/*	clear_message(); would be nice, but tin doesn't expect this yet */
	va_end(ap);
}
Exemple #2
0
size_t		my_fwrite(const void *ptr, size_t size,
			  size_t count, t_fle *file)
{
  size_t       	i;
  size_t       	j;
  const char	*tab;

  if (ptr == NULL || file == NULL || (size * count) > FILE_SZ_MAX ||
      (!(file->fmode & O_WRONLY) && !(file->fmode & O_RDWR)))
    return (-1);
  i = 0;
  j = 0;
  tab = ptr;
  while (j < (count * size))
    {
      while (((i + file->csr) < BUFF_SZ) && j < (count * size))
	file->buff[i++ + file->csr] = tab[j++];
      file->csr += i;
      file->state = NOT_FLUSHED;
      if (file->csr >= BUFF_SZ)
	{
	  my_flush(file);
	  i = 0;
	}
    }
  return ((size_t)j);
}
Exemple #3
0
int vrpn_Tracker_Dyna::get_status()
{
    int	    	bytesRead;
    unsigned char    	statusBuffer[256];

    my_flush();

    /* send request for status record   */

    vrpn_write_characters(serial_fd,(const unsigned char *) "\021", 1);
    vrpn_drain_output_buffer(serial_fd);
    vrpn_SleepMsecs(1000.0*2);

    /* do non-blocking read of status record    */
    bytesRead = vrpn_read_available_characters(serial_fd, statusBuffer, 8);
    // T_PDYN_STATUS_RECORD_LENGTH =8;

    if ( bytesRead == 8 )
    {
       /* we have correct length-  check a few chars to make sure this is a valid 
	* record
	*/
       if ( ((statusBuffer[0] & lOOO_OOOO) != lOOO_OOOO) ||
	    ((statusBuffer[1] & lOOO_OOOO) != lOOO_OOOO) )
	 return(T_ERROR);       

       /* otherwise, all is well   */
       return(T_OK);
    }

    /* if we get here, we either got too much data or not enough	*/

    /* no data means it's probably disconnected or not turned on	*/
    if ( bytesRead == 0 )
    {
//       fprintf(stderr, "No data\n");
      return(T_PDYN_NO_DATA);
    }

    /* if we got too much data, chances are that it's in continuous mode	*/
    if ( bytesRead > 8)
    {
       fprintf(stderr, "3\n");
      return(T_PDYN_SPEW_MODE);
    }

    /* if we get here, i have no idea what's going on-  could be garbage on the
     *  serial line, wrong baud rate, or that the Dynasight is flaking out.
     */
    return(T_ERROR);

}	/* t_pdyn_get_status */
Exemple #4
0
/*
 * Read .newsrc into my_group[]. my_group[] ints point to active[] entries.
 * If allgroups is set, then my_group[] is completely overwritten,
 * otherwise, groups are appended. Any bogus groups will be handled
 * accordingly. Bogus groups will _not_ be subscribed to as a design
 * principle.
 *
 * Returns the numer of lines read(useful for a check newsrc >= oldnewsrc)
 * 	< 0 error
 * 	>=0 number of lines read
 */
signed long int
read_newsrc(
	char *newsrc_file,
	t_bool allgroups)
{
	FILE *fp;
	char *grp, *seq;
	int sub, i;
	signed long line_count = 0;
	struct stat statbuf;

	if (allgroups)
		selmenu.max = skip_newgroups();

	/*
	 * make a .newsrc if one doesn't exist & auto subscribe to set groups
	 */
	if (stat(newsrc_file, &statbuf) == -1) {
		if (!create_newsrc(newsrc_file))
			return -1L; /* ouch */
		auto_subscribe_groups(newsrc_file);
	} else
		newsrc_mode = statbuf.st_mode;

	if ((fp = fopen(newsrc_file, "r")) != NULL) {
		if (!batch_mode || verbose)
			wait_message(0, _(txt_reading_newsrc));

		while ((grp = tin_fgets(fp, FALSE)) != NULL) {
			seq = parse_newsrc_line(grp, &sub);
			line_count++;

			if (sub == SUBSCRIBED) {
				if ((i = my_group_add(grp)) >= 0) {
					if (!active[my_group[i]].bogus) {
						active[my_group[i]].subscribed = SUB_BOOL(sub);
						parse_bitmap_seq(&active[my_group[i]], seq);
					}
				} else
					process_bogus(grp);
			}
		}
		fclose(fp);
		/* If you aborted with 'q', then you get what you get. */

		if (cmd_line) {
			my_fputc('\n', stdout);
			my_flush();
		}
	}
	return line_count;
}
Exemple #5
0
void
clear_message(
	void)
{
	if (!cmd_line) {
		MoveCursor(cLINES, 0);
		CleartoEOLN();
		cursoroff();
#ifndef USE_CURSES
		my_flush();
#endif /* !USE_CURSES */
	}
}
Exemple #6
0
void
ring_bell(
	void)
{
#ifdef USE_CURSES
	if (!cmd_line)
		beep();
	else {
#endif /* USE_CURSES */
	my_fputc('\007', stdout);
	my_flush();
#ifdef USE_CURSES
	}
#endif /* USE_CURSES */
}
Exemple #7
0
/*
** Control message from erlang, we handle $f, which is flush.
*/
static int trace_file_control(ErlDrvData handle, unsigned int command,
                              char* buff, int count,
                              char** res, int res_size)
{
    if (command == 'f') {
        TraceFileData *data = (TraceFileData *) handle;
        if (my_flush(data) < 0) {
            driver_failure_posix(data->port, errno); /* XXX */
        }
        if (res_size < 1) {
            *res = my_alloc(1);
        }
        **res = '\0';
        return 1;
    }
    return -1;
}
Exemple #8
0
void vrpn_Tracker_Dyna::reset() {
    //static int numResets = 0;	// How many resets have we tried?;
  static char T_PDYN_C_CTL_C[4] ="\003\003\003";
  static int T_PDYN_RECORD_LENGTH = 8;

  vrpn_write_characters(serial_fd, (unsigned char*)T_PDYN_C_CTL_C, strlen(T_PDYN_C_CTL_C));
  vrpn_write_characters(serial_fd,(const unsigned char *) "4", 1); // set to polling mode;
      
  /* pause 1 second to allow the Dynasight buffer to stabilize	*/
  vrpn_SleepMsecs(1000.0*1);

  status = get_status();
      
  if ( status != T_OK ) {

    /* if no data, tracker probably not connected.  just bag it.    */
    if ( status == T_PDYN_NO_DATA )
    {
      fprintf(stderr, "vrpn_Tracker_Dyna::reset(): no data (is tracker turned on?)\n"); 
      status = vrpn_TRACKER_RESETTING;
      return;

    } 
    
  }else {
    fprintf(stderr, "vrpn_Tracker_Dyna: return valid status report\n");
    reportLength = T_PDYN_RECORD_LENGTH;
    
    // set it to continues mode;
    /* clear any leftover data	*/
   my_flush();

   /* set the Dynasight to continuous mode    */
   vrpn_write_characters(serial_fd, (unsigned char*)T_PDYN_C_CTL_C, strlen(T_PDYN_C_CTL_C));
   //vrpn_write_characters(serial_fd, (const unsigned char *)"V", 1);
   vrpn_write_characters(serial_fd, (const unsigned char *)"0", 1);
   //T_PDYN_C_CONTINUOUS = "V"
   vrpn_SleepMsecs(1000.0*1);
   //vrpn_gettimeofday(&timestamp, NULL);	// Set watchdog now;
   timestamp.tv_sec = -1;
   status = vrpn_TRACKER_SYNCING;	// We are trying for a new reading;
   return;
  }
				     
}
Exemple #9
0
int	my_fclose(t_fle *file)
{
  if (file == NULL)
    return (0);
  gbgc_free(NULL, file->name);
  if ((file->fmode & O_WRONLY) || (file->fmode & O_RDWR))
    my_flush(file);
  if (file->fd >= 0)
    {
      if (close(file->fd) < 0)
	{
	  gbgc_free(NULL, file);
	  return (0);
	}
    }
  gbgc_free(NULL, file);
  return (1);
}
Exemple #10
0
void
spin_cursor(
	void)
{
	static const char buf[] = "|/-\\|/-\\ "; /* don't remove the tailing space! */
	static unsigned short int i = 0;

	if (batch_mode)
		return;

	if (i > 7)
		i = 0;

#ifdef HAVE_COLOR
	fcol(tinrc.col_message);
#endif /* HAVE_COLOR */
	my_printf("\b%c", buf[i++]);
	my_flush();
#ifdef HAVE_COLOR
	fcol(tinrc.col_normal);
#endif /* HAVE_COLOR */
}
Exemple #11
0
/*
 * progressmeter in %
 */
void
show_progress(
	const char *txt,
	long count,
	long total)
{
	char display[LEN];
	int ratio;
	time_t curr_time;
	static char last_display[LEN];
	static const char *last_txt;
	static int last_length;
	static int last_ratio;
	static long last_total;
	static time_t last_update;
#ifdef HAVE_GETTIMEOFDAY
	static long last_count;
	static int average;
	static int samples;
	static int sum;
	static struct timeval last_time;
	static struct timeval this_time;
	int time_diff;
	int secs_left;
	long count_diff;
#endif /* HAVE_GETTIMEOFDAY */

	if (batch_mode || count <= 0 || total == 0)
		return;

	/* If this is a new progress meter, start recalculating */
	if ((last_txt != txt) || (last_total != total)) {
		last_length = 0;
		last_ratio = -1;
		last_display[0] = '\0';
		last_update = time(NULL) - 2;
	}

	curr_time = time(NULL);
	ratio = (int) ((count * 100) / total);
	if ((ratio == last_ratio) && (curr_time - last_update < 2))
		/*
		 * return if ratio did not change and less than 1-2 seconds since last
		 * update to reduce output
		 */
		return;

	last_update = curr_time;

#ifdef HAVE_GETTIMEOFDAY
	if (last_length == 0) {
		/* Don't print a "time remaining" this time */
		snprintf(display, sizeof(display), "%s %3d%%", txt, ratio);
		display[sizeof(display) - 1] = '\0';
		last_length = strlen(txt) + 5;

		/* Reset the variables */
		sum = average = samples = 0;
	} else {
		/* Get the current time */
		gettimeofday(&this_time, NULL);
		time_diff = (this_time.tv_sec - last_time.tv_sec) * 1000000;
		time_diff += (this_time.tv_usec - last_time.tv_usec);

		count_diff = (count - last_count);

		if (!count_diff) /* avoid div by zero */
			count_diff++;

		/*
		 * Calculate a running average based on the last 20 samples. For the
		 * first 19 samples just add all and divide by the number of samples.
		 * From the 20th sample on use only the last 20 samples to calculate
		 * the running averave. To make things easier we don't want to store
		 * and keep track of all of them, so we assume that the first sample
		 * was close to the current average and substract it from sum. Then,
		 * the new sample is added to the sum and the sum is divided by 20 to
		 * get the new average.
		 */
		if (samples == 20) {
			sum -= average;
			sum += (time_diff / count_diff);
			average = sum / 20;
		} else {
			sum += (time_diff / count_diff);
			average = sum / ++samples;
		}

		if (average >= 1000000)
			secs_left = (total - count) * (average / 1000000);
		else
			secs_left = ((total - count) * average) / 1000000;

		if (secs_left < 0)
			secs_left = 0;

		/* TODO: -> lang.c, difficult with hardcoded last_length */
		snprintf(display, sizeof(display), "%s %3d%% (%d:%02d remaining)", txt, ratio, secs_left / 60, secs_left % 60);
		last_length = strlen(txt) + 21 + secs_left / 600;
	}

	last_count = count;
	gettimeofday(&last_time, NULL);

#else /* HAVE_GETTIMEOFDAY */
	snprintf(display, sizeof(display), "%s %3d%%", txt, ratio);
#endif /* HAVE_GETTIMEOFDAY */

	/* Only display text if it changed from last time */
	if (strcmp(display, last_display)) {
		clear_message();
		MoveCursor(cLINES, 0);

#	ifdef HAVE_COLOR
		fcol(tinrc.col_message);
#	endif /* HAVE_COLOR */

		my_printf("%s", display);

#	ifdef HAVE_COLOR
		fcol(tinrc.col_normal);
#	endif /* HAVE_COLOR */

		my_flush();
		STRCPY(last_display, display);
	}

	last_txt = txt;
	last_total = total;
	last_ratio = ratio;
}
Exemple #12
0
void
center_line(
	int line,
	t_bool inverse,
	const char *str)
{
	char buffer[256];
	int pos;
	int len;
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	int width;
	wchar_t wbuffer[256];	/* needs same number of elements as buffer */
	wchar_t wbuffer2[256];
	wchar_t suffix_buf[6];	/* space for TRUNC_TAIL */
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */

	STRCPY(buffer, str);

	/* protect terminal... */
	convert_to_printable(buffer);

#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	if ((len = mbstowcs(wbuffer, buffer, ARRAY_SIZE(wbuffer) - 1)) <= 0)
		len = strlen(buffer);
	else
		wbuffer[ARRAY_SIZE(wbuffer) - 1] = (wchar_t) '\0';
	if ((width = wcswidth(wbuffer, ARRAY_SIZE(wbuffer) - 1)) <= 0)
		width = len;
#else
	len = strlen(buffer);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */

	if (!cmd_line) {
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
		if (cCOLS >= width)
			pos = (cCOLS - width) / 2;
#else
		if (cCOLS >= len)
			pos = (cCOLS - len) / 2;
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
		else
			pos = 1;

		MoveCursor(line, pos);
		if (inverse) {
			StartInverse();
			my_flush();
		}
	}

#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	if (width >= cCOLS) {
		wcspart(wbuffer2, wbuffer, cCOLS - 6, ARRAY_SIZE(wbuffer2) - 5, TRUE);
		mbstowcs(suffix_buf, TRUNC_TAIL, ARRAY_SIZE(suffix_buf) - 1);
		wcsncat(wbuffer2, suffix_buf, 4);
		wcstombs(buffer, wbuffer2, sizeof(buffer) - 1);
	}
#else
	if (len >= cCOLS) {
		char *buf;

		buf = my_strdup(buffer);
		snprintf(buffer, sizeof(buffer), "%-.*s%s", cCOLS - 6, buf, TRUNC_TAIL);
		free(buf);
	}
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
	my_fputs(buffer, stdout);

	if (cmd_line)
		my_flush();
	else {
		if (inverse)
			EndInverse();
	}
}
Exemple #13
0
char *
tin_getline(
	const char *prompt,
	int number_only,	/* 1=positive numbers only, 2=negative too */
	const char *str,
	int max_chars,
	t_bool passwd,
	int which_hist)
{
	int c, i, loc, tmp, gl_max;
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	wint_t wc;
#else
	char *buf = gl_buf;
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */

	is_passwd = passwd;

	set_xclick_off();
	if (prompt == NULL)
		prompt = "";

	gl_buf[0] = 0;		/* used as end of input indicator */
	gl_fixup(-1, 0);	/* this resets gl_fixup */
	gl_width = cCOLS - strlen(prompt);
	gl_prompt = prompt;
	gl_pos = gl_cnt = 0;

	if (max_chars == 0) {
		if (number_only)
			gl_max = 6;
		else
			gl_max = BUF_SIZE;
	} else
		gl_max = max_chars;

	my_fputs(prompt, stdout);
	cursoron();
	my_flush();

	if (gl_in_hook) {
		loc = gl_in_hook(gl_buf);
		if (loc >= 0)
			gl_fixup(0, BUF_SIZE);
	}

	if (!cmd_line && gl_max == BUF_SIZE)
		CleartoEOLN();

#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	if (str != NULL) {
		wchar_t wbuf[LEN];

		if (mbstowcs(wbuf, str, ARRAY_SIZE(wbuf) - 1) != (size_t) -1) {
			wbuf[ARRAY_SIZE(wbuf) - 1] = (wchar_t) '\0';
			for (i = 0; wbuf[i]; i++)
				gl_addwchar(wbuf[i]);
		}
	}

	while ((wc = ReadWch()) != WEOF) {
		if ((gl_cnt < gl_max) && iswprint(wc)) {
			if (number_only) {
				if (iswdigit(wc)) {
					gl_addwchar(wc);
				/* Minus */
				} else if (number_only == 2 && gl_pos == 0 && wc == (wint_t) '-') {
					gl_addwchar(wc);
				} else {
					ring_bell();
				}
			} else
				gl_addwchar(wc);
		} else {
			c = (int) wc;
			switch (wc) {
#else
	if (str != NULL) {
		for (i = 0; str[i]; i++)
			gl_addchar(str[i]);
	}

	while ((c = ReadCh()) != EOF) {
		c &= 0xff;
		if ((gl_cnt < gl_max) && my_isprint(c)) {
			if (number_only) {
				if (isdigit(c)) {
					gl_addchar(c);
				/* Minus */
				} else if (number_only == 2 && gl_pos == 0 && c == '-') {
					gl_addchar(c);
				} else {
					ring_bell();
				}
			} else
				gl_addchar(c);
		} else {
			switch (c) {
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
				case ESC:	/* abort */
#ifdef HAVE_KEY_PREFIX
				case KEY_PREFIX:
#endif /* HAVE_KEY_PREFIX */
					switch (get_arrow_key(c)) {
						case KEYMAP_UP:
						case KEYMAP_PAGE_UP:
							hist_prev(which_hist);
							break;

						case KEYMAP_PAGE_DOWN:
						case KEYMAP_DOWN:
							hist_next(which_hist);
							break;

						case KEYMAP_RIGHT:
							gl_fixup(-1, gl_pos + 1);
							break;

						case KEYMAP_LEFT:
							gl_fixup(-1, gl_pos - 1);
							break;

						case KEYMAP_HOME:
							gl_fixup(-1, 0);
							break;

						case KEYMAP_END:
							gl_fixup(-1, gl_cnt);
							break;

						case KEYMAP_DEL:
							gl_del(0);
							break;

						case KEYMAP_INS:
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
							gl_addwchar((wint_t) ' ');
#else
							gl_addchar(' ');
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
							break;

						default:
							return (char *) 0;
					}
					break;

				case '\n':	/* newline */
				case '\r':
					gl_newline(which_hist);
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
					wcstombs(buf, gl_buf, BUF_SIZE - 1);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
					return buf;

				case CTRL_A:
					gl_fixup(-1, 0);
					break;

				case CTRL_B:
					gl_fixup(-1, gl_pos - 1);
					break;

				case CTRL_D:
					if (gl_cnt == 0) {
						gl_buf[0] = 0;
						my_fputc('\n', stdout);
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
						wcstombs(buf, gl_buf, BUF_SIZE - 1);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
						return buf;
					} else
						gl_del(0);
					break;

				case CTRL_E:
					gl_fixup(-1, gl_cnt);
					break;

				case CTRL_F:
					gl_fixup(-1, gl_pos + 1);
					break;

				case CTRL_H:
				case DEL:
					gl_del(-1);
					break;

				case TAB:
					if (gl_tab_hook) {
						tmp = gl_pos;
						loc = gl_tab_hook(gl_buf, strlen(gl_prompt), &tmp);
						if (loc >= 0 || tmp != gl_pos)
							gl_fixup(loc, tmp);
					}
					break;

				case CTRL_W:
					gl_kill_back_word();
					break;

				case CTRL_U:
					gl_fixup(-1, 0);
					/* FALLTHROUGH */
				case CTRL_K:
					gl_kill();
					break;

				case CTRL_L:
				case CTRL_R:
					gl_redraw();
					break;

				case CTRL_N:
					hist_next(which_hist);
					break;

				case CTRL_P:
					hist_prev(which_hist);
					break;

				default:
					ring_bell();
					break;
			}
		}
	}
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	wcstombs(buf, gl_buf, BUF_SIZE - 1);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
	return buf;
}


/*
 * adds the character c to the input buffer at current location if
 * the character is in the allowed template of characters
 */
static void
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
gl_addwchar(
	wint_t wc)
#else
gl_addchar(
	int c)
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
{
	int i;

	/*
	 * Crashing is always the worst solution IMHO. So as a quick hack,
	 * ignore characters silently, if buffer is full. To allow a final
	 * newline, leave space for one more character. Just a hack too.
	 * This was the original code:
	 *
	if (gl_cnt >= BUF_SIZE - 1) {
		error_message("tin_getline: input buffer overflow");
		giveup();
	}
	 */
	if (gl_cnt >= BUF_SIZE - 2)
		return;

	for (i = gl_cnt; i >= gl_pos; i--)
		gl_buf[i + 1] = gl_buf[i];

#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	gl_buf[gl_pos] = (wchar_t) wc;
#else
	gl_buf[gl_pos] = c;
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
	gl_fixup(gl_pos, gl_pos + 1);
}


/*
 * Cleans up entire line before returning to caller. A \n is appended.
 * If line longer than screen, we redraw starting at beginning
 */
static void
gl_newline(
	int w)
{
	int change = gl_cnt;
	int len = gl_cnt;
	int loc = gl_width - 5;	/* shifts line back to start position */

	if (gl_cnt >= BUF_SIZE - 1) {
		/*
		 * Like above: avoid crashing if possible. gl_addchar() now
		 * leaves one space left for the newline, so this part of the
		 * code should never be reached. A proper implementation is
		 * desirable though.
		 */
		error_message("tin_getline: input buffer overflow");
		giveup();
	}
	hist_add(w);		/* only adds if nonblank */
	if (gl_out_hook) {
		change = gl_out_hook(gl_buf);
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
		len = wcslen(gl_buf);
#else
		len = strlen(gl_buf);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
	}
	if (loc > len)
		loc = len;
	gl_fixup(change, loc);	/* must do this before appending \n */
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
	gl_buf[len] = (wchar_t) '\0';
#else
	gl_buf[len] = '\0';
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
}


/*
 * Delete a character. The loc variable can be:
 *    -1 : delete character to left of cursor
 *     0 : delete character under cursor
 */
static void
gl_del(
	int loc)
{
	int i;

	if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
		for (i = gl_pos + loc; i < gl_cnt; i++)
			gl_buf[i] = gl_buf[i + 1];
		gl_fixup(gl_pos + loc, gl_pos + loc);
	} else
		ring_bell();
}
Exemple #14
0
/*
 * This function is used both for redrawing when input changes or for
 * moving within the input line. The parameters are:
 *   change : the index of the start of changes in the input buffer,
 *            with -1 indicating no changes.
 *   cursor : the desired location of the cursor after the call.
 *            A value of BUF_SIZE can be used to indicate the cursor
 *            should move just past the end of the input line.
 */
static void
gl_fixup(
	int change,
	int cursor)
{
	static int gl_shift;	/* index of first on screen character */
	static int off_right;	/* true if more text right of screen */
	static int off_left;	/* true if more text left of screen */
	int left = 0, right = -1;	/* bounds for redraw */
	int pad;		/* how much to erase at end of line */
	int backup;		/* how far to backup before fixing */
	int new_shift;		/* value of shift based on cursor */
	int extra;		/* adjusts when shift (scroll) happens */
	int i;

	if (change == -1 && cursor == 0 && gl_buf[0] == 0) {	/* reset */
		gl_shift = off_right = off_left = 0;
		return;
	}
	pad = (off_right) ? gl_width - 1 : gl_cnt - gl_shift;	/* old length */
	backup = gl_pos - gl_shift;
	if (change >= 0) {
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
		gl_cnt = wcslen(gl_buf);
#else
		gl_cnt = strlen(gl_buf);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
		if (change > gl_cnt)
			change = gl_cnt;
	}
	if (cursor > gl_cnt) {
		if (cursor != BUF_SIZE)		/* BUF_SIZE means end of line */
			ring_bell();
		cursor = gl_cnt;
	}
	if (cursor < 0) {
		ring_bell();
		cursor = 0;
	}
	if (!is_passwd) {
		if (off_right || (off_left && (cursor < gl_shift + gl_width - SCROLL / 2)))
			extra = 2;	/* shift the scrolling boundary */
		else
			extra = 0;
		new_shift = cursor + extra + SCROLL - gl_width;
		if (new_shift > 0) {
			new_shift /= SCROLL;
			new_shift *= SCROLL;
		} else
			new_shift = 0;
		if (new_shift != gl_shift) {	/* scroll occurs */
			gl_shift = new_shift;
			off_left = (gl_shift) ? 1 : 0;
			off_right = (gl_cnt > gl_shift + gl_width - 1) ? 1 : 0;
			left = gl_shift;
			right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
		} else if (change >= 0) {	/* no scroll, but text changed */
			if (change < gl_shift + off_left)
				left = gl_shift;
			else {
				left = change;
				backup = gl_pos - change;
			}
			off_right = (gl_cnt > gl_shift + gl_width - 1) ? 1 : 0;
			right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
		}
		pad -= (off_right) ? gl_width - 1 : gl_cnt - gl_shift;
		pad = (pad < 0) ? 0 : pad;
		if (left <= right) {	/* clean up screen */
			for (i = 0; i < backup; i++)
				my_fputc('\b', stdout);
			if (left == gl_shift && off_left) {
				my_fputc('$', stdout);
				left++;
			}
			for (i = left; i < right; i++) {
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
				my_fputwc((wint_t) gl_buf[i], stdout);
#else
				my_fputc(gl_buf[i], stdout);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
			}
			if (off_right) {
				my_fputc('$', stdout);
				gl_pos = right + 1;
			} else {
				for (i = 0; i < pad; i++)	/* erase remains of prev line */
					my_fputc(' ', stdout);
				gl_pos = right + pad;
			}
		}
		i = gl_pos - cursor;	/* move to final cursor location */
		if (i > 0) {
			while (i--)
				my_fputc('\b', stdout);
		} else {
			for (i = gl_pos; i < cursor; i++) {
#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
				my_fputwc((wint_t) gl_buf[i], stdout);
#else
				my_fputc(gl_buf[i], stdout);
#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
			}
		}
		my_flush();
	}
	gl_pos = cursor;
}