Пример 22



/* ______________________________________________________________ */

/*      ПРЯМОУГОЛЬНАЯ ТАБЛИЦА-МЕНЮ                                */

/* _______________________ файл table.h _________________________ */

typedef struct _Table { /* Паспорт таблицы                */

	int nitems;     /* количество элементов в таблице */

	Info *items;    /* массив элементов               */

	char *fmt;      /* формат вывода                  */

	int key;        /* кнопка, завершившая выбор в таблице */

	int current;    /* номер выбранного элемента      */

	int shift;      /* число элементов перед окном    */

	WINDOW *win;    /* окно в котором размещена таблица */

	int left, top, height, width; /* размеры и расположение

			   таблицы в окне */

	int space;      /* интервал между колонками   */

	int elen;       /* макс. ширина колонки       */

	int tcols;      /* число колонок в таблице    */

	int cols;       /* число колонок в видимой части таблицы       */

	int cutpos;     /* позиция для обрубания слишком длинных строк */

	int scrollok;   /* роллируется ? */

	int exposed;    /* нарисована  ? */

	int elems;      /* текущее число эл-тов в подокне      */

	int maxelems;   /* максимальное число эл-тов в подокне */

	int maxshift;   /* максимальный сдвиг */

	int bg_attrib, sel_attrib;      /* цвет фона и выбранного

					   элемента */

	Point   savep;

	/* Функции проявки/спрятывания окна */

	int  (*showMe)(struct _Table *tbl);

	void (*hideMe)(struct _Table *tbl);

void (*scrollBar)(struct _Table *tbl, int whichbar, int n, int among);

	/* Обработчик специальных клавиш */

	int *hitkeys;

	int (*handler)(struct _Table *tbl, int c, HandlerReply *reply);

} Table;

#define T_BOLD       M_BOLD

#define T_NOSEL      I_NOSEL

#define T_HATCH      M_HATCH

#define T_LABEL      M_LABEL

#define T_SET(m, i, flg)        (((m)->items)[i]).fl  |=  (flg)

#define T_CLR(m, i, flg)        (((m)->items)[i]).fl  &= ~(flg)

#define T_TST(m, i, flg)        ((((m)->items)[i]).fl &   (flg))

#define T_ITEM(m, i)            ((((m)->items)[i]).s)

/* Формат 'd' ниже вставлен лишь для текущего состояния использования

 * форматов в нашем проекте:      */

#define T_ITEMF(m, i, cut)        \

  ((m)->fmt && *(m)->fmt != 'd' ? \

	TblConvert(T_ITEM((m), i), (m)->fmt, (cut)) : T_ITEM((m), i))

#define T_VISIBLE(tbl, new)   ((tbl)->exposed == YES && \

  (new) >= (tbl)->shift && (new) < (tbl)->shift + (tbl)->elems)

#define TLABSIZE        2  /* ширина поля меток */

#define T_REFUSED(t)	((t)->key < 0 || (t)->key == ESC )

int TblCount( Table *tbl );

void TblInit( Table *tbl, int forcedOneColumn );

void TblChkCur  ( Table *tbl );

int  TblChkShift( Table *tbl );

void TblChk     ( Table *tbl );

char *TblConvert( char *s, char *fmt, int cutpos );

void TblPointAt ( Table *tbl, int snew );

void TblPoint   ( Table *tbl, int snew, int eraseOld );

void TblDraw    ( Table *tbl );

void TblDrawItem( Table *tbl, int at, int reverse, int selection);

void TblBox     ( Table *tbl, int at, int reverse, int hatched,

		  int width, int axl, int axi, int ay);

int  TblClear( Table *tbl );

int  TblPlaceByName( Table *tbl, char *p );

void TblReport( Table *tbl );

void TblTag  ( Table *tbl, int at, int flag);

void TblUntag( Table *tbl, int at, int flag);

void TblRetag( Table *tbl, int at, int flag);

void TblTagAll( Table *tbl, char *pattern, int flag );

void TblUntagAll( Table *tbl, char *pattern, int flag );

int  TblUsualSelect( Table *tbl );

/* _______________________ файл table.c _________________________ */

#include "w.h"

#include "glob.h"

#include "menu.h"

#include "table.h"

extern char STRING_BUFFER[MAXLEN]; /* imported from menu.c */

/* надо указать размер, чтоб работал sizeof(STRING_BUFFER) */

/* Переформатировать строку по формату fmt для выдачи в таблицу.

 * Пока предложена простейшая интерпретация. */

char *TblConvert( char *s, char *fmt, int cutpos ){

    if( fmt && *fmt == 'd'){

	register i, j, len; char *p = strrchr(s, '.');

	if((len = strlen(s)) < DIR_SIZE && *s != '.' && p ){

	  int sufxlen = strlen(p);

	  for(i=0; i < len - sufxlen  ; ++i) STRING_BUFFER[i] = s[i];

	  for(; i < DIR_SIZE - sufxlen; ++i) STRING_BUFFER[i] = ' ';

	  for(j=0; i < DIR_SIZE; j++,   ++i) STRING_BUFFER[i] = p[j];

	  STRING_BUFFER[i] = '\0';

	} else strcpy(STRING_BUFFER, s);

	if(cutpos > 0 && cutpos < sizeof(STRING_BUFFER))

		STRING_BUFFER[cutpos] = '\0';

    } else {  /* без формата, только обрубание */

       if( cutpos <= 0 ) cutpos = 32000; /* Обрубание выключено */

       strncpy(STRING_BUFFER, s, MIN(sizeof(STRING_BUFFER) - 1, cutpos));

    }

    return STRING_BUFFER;

}

/* Обрубить s до длины cutpos букв */

char *TblCut( char *s, int cutpos ){

    if( cutpos <= 0 ) return s;

    strncpy(STRING_BUFFER, s, MIN(sizeof(STRING_BUFFER) - 1, cutpos));

	return STRING_BUFFER;

}

/* Подсчет элементов таблицы и ширины столбца */

int TblCount( Table *tbl ){

	register i, L, LL; char *s;

	L = i = 0;

	if( tbl->items)

	    while((s = T_ITEM(tbl, i)) != NULL ){

		if( tbl->fmt )

			s = TblConvert(s, tbl->fmt, 0);

		LL = strlen(s);

		if( LL > L ) L = LL;

		i++;

	    }

	tbl->nitems = i; return L;

}

/* Разметка таблицы. На входе:

	t->items          Массив данных, показываемый в меню.

	t->exposed = NO   Таблица уже нарисована ?

	t->fmt            Формат строк, выводимых в таблицу.

	t->win            Окно для размещения таблицы.

	t->showMe         Функция проявки окна.

	t->hideMe         Функция упрятывания окна.

	t->hitkeys        Специальные клавиши []. Конец -1.

	t->handler        Обработчик или NULL.

	t->width          Ширина поля таблицы.

	t->height         Высота поля таблицы.

	t->left           Левый край таблицы в окне.

	t->top            Верхний край таблицы в окне.

	t->scrollBar      Функция рисования scroll-bar-а или NULL.

	t->bg_attrib      Цвет фона (== цвету фона окна).

	t->sel_attrib     Цвет выбранного элемента.

	forcedOneColumn == YES делает таблицу в 1 колонку.

*/

void TblInit( Table *tbl, int forcedOneColumn ){

	int mlen = TblCount( tbl ); /* самый широкий элемент таблицы */

     /* усечь до ширины таблицы */

	if( mlen > tbl->width || forcedOneColumn )

		mlen = tbl->width; /* слишком широко */

/* ширина столбца таблицы = ширина элемента + поле меток + разделитель */

	tbl->elen = mlen + TLABSIZE + 1;

	/*     #####строка_элемент|     */

	/*     метки   элемент    1     */

     /* число столбцов во всей таблице */

	tbl->tcols = (tbl->nitems + tbl->height - 1) / tbl->height;

     /* число столбцов, видимых через окно (+1 для ошибок округления) */

	tbl->cols  = tbl->width / (tbl->elen + 1);

	if( tbl->cols == 0 ){   /* слишком широкая таблица */

		tbl->cols = 1;  /* таблица в одну колонку  */

		tbl->elen = tbl->width - 2;

		mlen = tbl->elen - (TLABSIZE + 1);

		tbl->cutpos = mlen;  /* и придется обрубать строки */

	} else  tbl->cutpos = 0;     /* без обрубания              */

	tbl->cols  = MIN(tbl->cols, tbl->tcols);

     /* интервал между колонками */

	tbl->space = (tbl->width - tbl->cols * tbl->elen)/(tbl->cols+1);

	if( tbl->space < 0 ){ beep(); tbl->space = 0; }

     /* сколько элементов умещается в окно */

	tbl->maxelems = tbl-> cols *  tbl->height;

	tbl->maxshift = (tbl->tcols * tbl->height) - tbl->maxelems;

	if( tbl->maxshift < 0 ) tbl->maxshift = 0;

     /* требуется ли роллирование таблицы через окно */

	tbl->scrollok = (tbl->nitems > tbl->maxelems);

	tbl->elems    = tbl->shift = tbl->current = 0;  /* пока */

	tbl->exposed  = NO;     /* таблица еще не нарисована */

	tbl->key      = (-1);

}

/* Проверить корректность текущей позиции */

void TblChkCur( Table *tbl ){

	if( tbl->current >= tbl->nitems )

		tbl->current = tbl->nitems - 1;

	if( tbl->current < 0 )

		tbl->current = 0;

}

/* Проверить корректность сдвига (числа элементов ПЕРЕД окном) */

int TblChkShift( Table *tbl ){

	register int oldshift = tbl->shift;

	/* в колонке должно быть видно достаточно много элементов */

	if( tbl->cols == 1 &&   /* таблица в 1 колонку */

	    tbl->tcols > 1 &&   /* но всего в ней не одна колонка */

	    tbl->nitems - tbl->shift < tbl->height / 2 + 1

	)   tbl->shift = tbl->nitems - (tbl->height/2 + 1);

	if( tbl->shift > tbl->maxshift )

	    tbl->shift = tbl->maxshift;

	if( tbl->shift < 0 )

	    tbl->shift = 0;

	return tbl->shift != oldshift; /* скорректировано ? */

}

/* Проверить корректность параметров таблицы */

void TblChk( Table *tbl ){

again:

     TblChkCur( tbl ); TblChkShift( tbl );

     if( tbl -> maxelems ){

       if( tbl -> current >= tbl->shift + tbl->maxelems ){

	   tbl->shift = tbl->current - (tbl->maxelems - 1);

	   goto again;

       }

       if( tbl->current < tbl->shift ){

	   tbl->shift = tbl->current; goto again;

       }

     }

}

/* Указать на snew-тый элемент списка, перерисовать картинку */

void TblPointAt( Table *tbl, int snew ){

     int curCol; /* текущий столбец всей таблицы (для current) */

     int newCol; /* нужный столбец таблицы       (для snew)    */

     int colw;   /* нужный столбец ОКНА          (для snew)    */

     int gap;    /* зазор */

     int newshift = tbl->shift; /* новый сдвиг окна от начала массива */

     int drawn = NO;  /* таблица целиком перерисована ? */

     /* ПРоверить корректность номера желаемого элемента */

     if( snew < 0 ) snew = 0;

     if( snew >= tbl->nitems ) snew = tbl->nitems - 1;

     if( tbl->current == snew && tbl->exposed == YES)

	 return; /* уже стоим на требуемом элементе */

#define WANTINC 1

#define WANTDEC (tbl->cols-1-WANTINC)

	gap = (tbl->height - (tbl->shift % tbl->height)) % tbl->height;

     /* gap - это смещение, которое превращает строгую

	постолбцовую структуру

		 --0--        --3-		 --1--        --4-		 --2--        --5-	в сдвинутую структуру

	     ____                          |-----    gap=2___/    пусто g0     --1-- g3     |    --4-- g6      ....

	    \____пусто g1     --2-- g4     |    --5-- g7

		 --0-- g2     --3-- g5     |    --6-- g8

					   |------ shift=4

	*/

/* операция прокрутки данных через таблицу: TblRoll() _________________*/

	/* Элемент уже виден в текущем окне ?     */

	/* Параметр elems вычисляется в TblDraw() */

	if( T_VISIBLE(tbl, snew))

		goto ThisWindow;

	/* smooth scrolling (гладкое роллирование) */

	if( snew == tbl->shift + tbl->elems &&

	    /* элемент непосредственно следующий ЗА окном */

	    tbl->current == tbl->shift + tbl->elems - 1

	    /* курсор стоит в нижнем правом углу окна */

	){

	    newshift++; gap--;

	    if ( gap < 0 ) gap = tbl->height - 1 ;

	    goto do_this;

	}

	if( snew == tbl->shift - 1  &&

	    /* элемент непосредственно стоящий ПЕРЕД окном */

	    tbl->current == tbl->shift

	    /* и курсор стоит в верхнем левом углу окна таблицы */

	){

	    newshift --; gap = (gap + 1) % tbl->height;

	    goto do_this;

	}

	/* jump scrolling (прокрутка скачком) */

	curCol = (tbl->current+gap) / tbl->height;

	newCol = (snew        +gap) / tbl->height;

	if( tbl->cols > 1 ){

		if( newCol > curCol ) colw = WANTINC;

		else                  colw = WANTDEC;

	} else  colw = 0;

	newshift = (newCol - colw) * tbl->height  -  gap ;

do_this:

	if( tbl->shift != newshift || tbl->exposed == NO){

	   tbl->shift = newshift;

	   TblChkShift( tbl ); /* >= 0  && <= max */

	   TblDraw( tbl );     /* перерисовать все окно с нового места */

	   drawn = YES;        /* перерисовано целиком */

	}

ThisWindow: /* поставить курсор в текущем окне без перерисовки окна */

	TblPoint( tbl,  snew, !drawn );

	/* tbl->current = snew; сделается в TblPoint() */

}

/* Поставить курсор на элемент в текущем окне */

void TblPoint ( Table *tbl, int snew, int eraseOld ){

	if( ! T_VISIBLE(tbl, snew)){

		beep(); /* ERROR !!! */ return;

	}

	if( eraseOld && tbl->current != snew )

	    TblDrawItem( tbl, tbl->current, NO, YES );

	TblDrawItem( tbl, snew, YES, YES );

	tbl->current = snew;

	TblReport( tbl );

}

/* Нарисовать scroll bar в нужной позиции. Кроме того,

 * в эту функцию можно включить и другие действия, например

 * выдачу имени T_ITEM(tbl, tbl->current) на рамке окна. */

void TblReport( Table *tbl ){

     if ( tbl->scrollBar )

	(*tbl->scrollBar)( tbl, BAR_VER|BAR_HOR,

			   tbl->current, tbl->nitems);

     GetBack( tbl->savep, tbl->win ); /* курсор на место ! */

}

/* Перерисовать все окно таблицы */

void TblDraw( Table *tbl ){

     register next;

     /* число элементов в таблице (может остаться незанятое

      * место в правой нижней части окна */

     tbl->elems = MIN(tbl->nitems - tbl->shift, tbl->maxelems );

     for( next = 0; next < tbl->maxelems; next++ )

       TblDrawItem(tbl, next + tbl->shift, NO, tbl->scrollok ? YES : NO);

     tbl->exposed = YES; /* окно изображено */

}

/* Нарисовать элемент таблицы */

void TblDrawItem( Table *tbl, int at, int reverse, int selection){

     register WINDOW *w = tbl->win;

     int pos; char *s; int hatch, bold, label, under;

     int ax, axl, ay, column;

     if( at >= 0 && at < tbl->nitems ){

	 s =     T_ITEM( tbl, at );

	 if( tbl->fmt )

	     s = TblConvert(s, tbl->fmt, tbl->cutpos);

	 else if( tbl->cutpos > 0 )

	     s = TblCut(s, tbl->cutpos);

	 /* выделения */

	 hatch = T_TST( tbl,  at, T_HATCH );

	 bold  = T_TST( tbl,  at, T_BOLD  );

	 label = T_TST( tbl,  at, T_LABEL );

	 under = T_TST( tbl,  at, I_EXE   );

     } else { s = "~"; label = hatch = bold = under = NO; }

     at -= tbl->shift; /* координату в списке перевести в коорд. окна */

     ay  = tbl->top + at % tbl->height;

     column = at / tbl->height;

     /* начало поля меток */

     axl = tbl->left + tbl->space + column * (tbl->space + tbl->elen);

     /* начало строки-элемента */

     ax = axl + TLABSIZE;

     if(selection)

       TblBox( tbl, at, reverse, reverse && hatch, strlen(s), axl, ax, ay );

     wattrset (w, reverse ? tbl->sel_attrib : tbl->bg_attrib);

     if( hatch ) wattron(w, A_ITALICS);

     if( bold  ) wattron(w, A_BOLD);

     if( under ) wattron(w, A_UNDERLINE);

     mvwaddstr(w, ay, ax, s);

     wattrset(w, tbl->bg_attrib | (bold ? A_BOLD:0));

     if( label )                      mvwaddch(w, ay, axl,   LABEL);

     if( under ){ wattron(w, A_BOLD); mvwaddch(w, ay, axl+1, BOX_HATCHED);}

     wattrset(w, tbl->bg_attrib);

     if( column != tbl->cols-1 ) /* не последний столбец */

	mvwaddch(w, ay, axl+tbl->elen-1 + (tbl->space+1)/2, VER_LINE);

     wmove(w, ay, ax-1);             /* курсор перед началом строки   */

     SetPoint(tbl->savep, ay, ax-1); /* запомнить координаты курсора */

}

/* Зачистить область окна для рисования элемента таблицы */

void TblBox(Table *tbl, int at, int reverse, int hatched,

     int width, int axl, int axi, int ay){

     register WINDOW *w = tbl->win;

     int len = tbl->elen;

     wattrset (w, tbl->bg_attrib);

     wboxerase(w, axl, ay, axl+len-1, ay);

     wattrset (w, reverse ? tbl->sel_attrib : tbl->bg_attrib);

     /* если ниже задать   axl+len+1, то подсвеченный

      * прямоугольник будет фиксированного размера    */

     wboxerase(w, axi, ay, axl+width-1, ay);

     wattrset (w, tbl->bg_attrib);

}

/* Зачистить прямоугольную рабочую область окна tbl->win,

 * в которой будет изображаться таблица.

 * Эта функция нигде не вызывается ЯВНО, поэтому ВЫ должны

 * вызывать ее сами после каждого TblInit()

 * для этого удобно поместить ее в демон (*showMe)();

 */

int TblClear( Table *tbl ){

	tbl->exposed = NO;

	tbl->elems = 0;   /* Это всегда происходит при exposed:= NO */

	wboxerase( tbl->win,

		tbl->left, tbl->top,

		tbl->left + tbl->width - 1,

		tbl->top  + tbl->height - 1);

	return 1;

}

/* Пометить элемент в таблице */

void TblTag( Table *tbl, int at, int flag){

	if( T_TST(tbl, at, flag)) return;

	T_SET(tbl, at, flag);

	if( T_VISIBLE(tbl, at))

	    TblDrawItem(tbl, at, tbl->current == at ? YES:NO, YES );

}

/* Снять пометку с элемента таблицы */

void TblUntag( Table *tbl, int at, int flag){

	if( ! T_TST(tbl, at, flag)) return;

	T_CLR(tbl, at, flag);

	if( T_VISIBLE(tbl, at))

	    TblDrawItem(tbl, at, tbl->current == at ? YES:NO, YES );

}

/* Изменить пометку элемента таблицы */

void TblRetag( Table *tbl, int at, int flag){

	if( T_TST(tbl, at, flag)) T_CLR(tbl, at, flag);

	else                      T_SET(tbl, at, flag);

	if( T_VISIBLE(tbl, at))

	    TblDrawItem(tbl, at, tbl->current == at ? YES:NO, YES );

}

/* Используется в match() для выдачи сообщения об ошибке */

void TblMatchErr(){}

/* Пометить элементы, чьи имена удовлетворяют шаблону */

void TblTagAll( Table *tbl, char *pattern, int flag ){

     register i;

     for(i=0; i < tbl->nitems; i++)

     if( !T_TST(tbl, i, I_DIR) && match( T_ITEMF(tbl, i, 0), pattern))

	  TblTag( tbl, i, flag );

}

/* Снять пометки с элементов по шаблону имени */

void TblUntagAll( Table *tbl, char *pattern, int flag ){

     register i;

     for(i=0; i < tbl->nitems; i++)

	 if( match( T_ITEMF(tbl, i, 0), pattern))

	     TblUntag( tbl, i, flag );

}

/* Указать на элемент по шаблону его имени */

int TblPlaceByName( Table *tbl, char *p ){

	register i; char *s;

	for( i=0; i < tbl->nitems; i++ ){

	     s = T_ITEMF(tbl, i, 0);

	     if( match( s, p )){

		 if( tbl->exposed == NO ){

		     /* Задать некорректный shift,

		      * чтобы окно полностью перерисовалось */

		     tbl->shift = tbl->nitems+1; tbl->elems = 0;

		 }

		 TblPointAt( tbl, i );

		 return i;

	     }

	} return (-1);

}

/* Перемещение по таблице набором первых букв названия элемента */

static int TblTrack( Table *tbl, int c){

	char *s; register i;

	int from;  /* с какого элемента начинать поиск */

	int found   = 0; /* сколько было найдено */

	int plength = 0;

	int more    = 0;

	char pattern[20];

	if( c >= 0400 || iscntrl(c)){ beep(); return 0; }

AddCh:

	from = 0;

	pattern[plength] = c;

	pattern[plength+1] = '*';

	pattern[plength+2] = '\0';

	plength++;

More:

	for(i = from; i < tbl->nitems; i++){

	    s = T_ITEMF(tbl, i, 0);

	    if( match(s, pattern)){

		++found; from = i+1;

		TblPointAt( tbl, i );

		c = WinGetch( tbl->win );

		switch(c){

		case '\t':   /* find next matching */

			more++;

			goto More;

		case KEY_BACKSPACE: case '\177': case '\b':

			if( plength > 1 ){

				plength--;

				pattern[plength]   = '*';

				pattern[plength+1] = '\0';

				from = 0; more++;

				goto More;

			} else goto out;

		default:

			if( c >= 0400 || iscntrl(c))        return c;

			if( plength >= sizeof pattern - 2 ) goto out;

			goto AddCh;

		}

	    }

	}

	/* не найдено */

	if(more && found){ /* нет БОЛЬШЕ подходящих, но ВООБЩЕ - есть */

	       beep(); more = found = from = 0; goto More; }

out:    beep(); return 0;

}

/* Выбор в таблице */

int TblUsualSelect( Table *tbl ){

	int c, want;

	tbl->key = (-1);

	if( tbl->items == NULL || tbl->nitems <= 0 ) return TOTAL_NOSEL;

	TblChk( tbl );

	if( tbl->showMe )

		if((*tbl->showMe)(tbl) <= 0 )

			return (-1);

	if( !tbl->win ) return TOTAL_NOSEL;

	if( tbl->exposed == NO ){

	    TblDraw ( tbl );

	}

	/* Указать текущий элемент */

	TblPoint( tbl, tbl->current, NO);

	TblReport( tbl );

	for( ;; ){

		c = WinGetch(tbl->win);

	INP:

		if( tbl->hitkeys && tbl->handler ){

		    HandlerReply reply;

		    if( is_in(c, tbl->hitkeys)){

			c = (*tbl->handler)(tbl, c, &reply);

			TblReport( tbl ); /* restore scroll bar */

			switch( reply ){

			case HANDLER_CONTINUE:   continue;

			case HANDLER_NEWCHAR:    goto INP;

			case HANDLER_OUT:        goto out;

			case HANDLER_SWITCH:

			default: break;  /* goto switch(c) */

			}

		    }

		}

sw:             switch( c ){

		case KEY_LEFT:

			want = tbl->current - tbl->height; goto mv;

		case KEY_RIGHT:

			want = tbl->current + tbl->height; goto mv;

		case KEY_UP:

			want = tbl->current - 1; goto mv;

		case KEY_DOWN:

		next:

			want = tbl->current + 1; goto mv;

		case KEY_HOME:

			want = 0;                goto mv;

		case KEY_END:

			want = tbl->nitems - 1;  goto mv;

		case KEY_NPAGE:

			want = tbl->current + tbl->elems; goto mv;

		case KEY_PPAGE:

			want = tbl->current - tbl->elems; goto mv;

		case KEY_IC:

			if( T_TST(tbl, tbl->current, T_LABEL ))

				T_CLR(tbl, tbl->current, T_LABEL );

			else    T_SET(tbl, tbl->current, T_LABEL);

			if( tbl->current == tbl->nitems - 1 /* LAST */){

				TblPoint(tbl, tbl->current, NO );

				break;

			}

			TblPointAt(tbl, tbl->current );

			/* if not       goto next;

			 * but          break;

			 * then use

			 *      TblPoint(tbl, tbl->current, NO);

			 * here

			 */

			goto next;

		case KEY_DC:

			if( T_TST(tbl, tbl->current, T_HATCH ))

				T_CLR(tbl, tbl->current, T_HATCH );

			else    T_SET(tbl, tbl->current, T_HATCH);

			if( tbl->current == tbl->nitems - 1 /* LAST */){

				TblPoint(tbl, tbl->current, NO );

				break;

			}

			TblPointAt(tbl, tbl->current );

			goto next;

		case ESC:

		case '\r':

		case '\n':

			goto out;

		case 0: break;

		default:

			c = TblTrack(tbl, c);

			if( c ) goto  INP;

			break;

		}

		continue;

	mv:     TblPointAt( tbl, want );

	}

out:    wnoutrefresh( tbl->win );

	if( tbl->hideMe ) (*tbl->hideMe)(tbl);

	return ((tbl->key = c) == ESC ? -1 : tbl->current );

}

[Назад][Содержание][Вперед]

Используются технологии uCoz