Новые книги

Простым и понятным языком рассказано, как скрыть свое местонахождение и IP-адрес, используя анонимные сети Tor и I2P, посетить заблокированные администратором сайты, защитить личную переписку от посторонних глаз, избавиться от спама, зашифровать программой TrueCrypt данные, хранящиеся на жестком диске и передающиеся по сети. Отдельное внимание уделено защите домашней сети от нежданных гостей, от соседей, использующих чужую беспроводную сеть, выбору антивируса и брандмауэра (на примере Comodo Internet Security). Показано, как защитить свою страничку в социальной сети, удалить файлы без возможности восстановления и многое другое.

Для широкого круга пользователей
Все мы хотим быть финансово независимыми, но лишь немногие знают, как этого добиться. Для остальных же надежным подспорьем может послужить данная книга. Ее автор постарался как можно доходчивее расширить кругозор читателей в плане финансовой грамотности и научить их основным правилам обращения с деньгами. Как организовать контроль над расходами, как создать пассивный доход, в каком банке открыть вклад, какие приобретать облигации – об этих и других вещах он рассуждает со знанием дела, поскольку прежде опробовал их на собственной практике. Пожалуй, самый обстоятельный раздел посвящен акциям, в котором автор тщательно разбирает их достоинства и недостатки на примере ведущих российских компаний, давая дельные и конкретные советы по их приобретению.

Издание адресовано широкому кругу читателей, тем, кто хочет научиться распоряжаться своими финансами, грамотно копить и инвестировать деньги.

Примеры.

Пример 19

/* ________________________файл menu.h __________________________ */
/*                     РОЛЛИРУЕМОЕ МЕНЮ                           */
/* _______________________________________________________________*/
#include              <ctype.h>
#include              <sys/param.h>
#define M_HOT         '\\'      /* горячий ключ */
#define M_CTRL        '\1'      /* признак горизонтальной черты */
#define MXEND(m)      XEND((m)->win,(m)->scrollok)
#define NOKEY        (-33)      /* горячего ключа нет         */
#define MAXLEN       MAXPATHLEN /* макс. длина имен файлов    */
typedef enum { /* Коды, возвращаемые handler-ом (HandlerReply *reply) */
    HANDLER_OUT      = 0,  /* выйти из функции выбора          */
    HANDLER_CONTINUE = 1,  /* читать очередную букву           */
    HANDLER_NEWCHAR  = 2,  /* пойти на анализ кода handler-ом. */
    HANDLER_SWITCH   = 3,  /* пойти на switch()                */
    HANDLER_AGAIN    = 4   /* перезапустить всю функцию выбора */
} HandlerReply;
typedef struct _Menu {          /* паспорт меню               */
    int     nitems;             /* число элементов меню       */
    Info   *items;              /* сам массив элементов       */
    int    *hotkeys;            /* "горячие" клавиши          */
    int     key;		/* клавиша, завершившая выбор */
    int     current;            /* текущая строка списка      */
    int     shift;              /* сдвиг окна от начала меню  */
    int     scrollok;           /* окно роллируемое ?         */
    WINDOW *win;                /* окно для меню              */
    int     left, top, height, width; /* координаты меню на экране и
					 размер окна win       */
    int     textwidth, textheight;    /* размер подокна выбора */
    int     bg_attrib;          /* атрибут фона окна           */
    int     sel_attrib;         /* атрибут выбранной строки    */
    char   *title;              /* заголовок меню              */
    Point   savep;
    void  (*showMe)    (struct _Menu *m);
    void  (*scrollBar) (struct _Menu *m, int n, int among);
    int    *hitkeys;            /* клавиши, обрабатываемые особо */
    int   (*handler)   (struct _Menu *m, int c, HandlerReply *reply);
} Menu;
/* Структура окна с меню:
	*--------------*    +0
	|  ЗАГОЛОВОК   |    +1
	*-----------*--*    +2
	|+ стр1ааа  |  |    +3
	|  стр2ббб  |##| <- scroll bar шириной BARWIDTH
	|  стр3ввв  |  |
	*___________|__*
	|DX| len |DX|BS|
 */
/* Метки у элементов меню */
#define M_BOLD       I_DIR      /* яркая строка */
#define M_HATCH      0x08       /* строка тусклая     */
#define M_LFT        0x10       /* для использования в pulldown menu */
#define M_RGT        0x20       /* для использования в pulldown menu */
#define M_LABEL      0x40       /* строка имеет метку */
#define M_LEFT       (-111)
#define M_RIGHT      (-112)
#define TOTAL_NOSEL  (-I_NOSEL)
#define M_SET(m, i, flg)        (((m)->items)[i]). fl |=  (flg)
#define M_CLR(m, i, flg)        (((m)->items)[i]). fl &= ~(flg)
#define M_TST(m, i, flg)        ((((m)->items)[i]).fl &   (flg))
#define M_ITEM(m, i)            ((((m)->items)[i]).s)
	/* Прототипы */
int  MnuInit (Menu *m); void MnuDeinit (Menu *m);
void MnuDrawItem (Menu * m, int y, int reverse, int selection);
int     MnuNext (Menu *m); int     MnuPrev (Menu *m);
int     MnuFirst(Menu *m); int     MnuLast (Menu *m);
int     MnuPgUp (Menu *m); int     MnuPgDn (Menu *m);
int     MnuThis (Menu *m); int     MnuHot  (Menu *m, unsigned c);
int     MnuName (Menu *m, char *name);
void MnuDraw        (Menu *m);     void MnuHide(Menu *m);
void MnuPointAt     (Menu *m, int y);
void MnuPoint       (Menu *m, int line, int eraseOld);
int  MnuUsualSelect (Menu *m, int block);
int is_in(register int c, register int s[]);
char *MnuConvert    (char *s, int *pos);
#define M_REFUSED(m)    ((m)->key < 0 || (m)->key == ESC )
#define MNU_DY           1
/* _______________________ файл menu.c __________________________ */
#include "w.h"
#include "glob.h"
#include "menu.h"
#include <signal.h>
/* ---------------- implementation module ------------------------- */
/* Не входит ли символ в специальный набор? Массив завершается (-1) */
int is_in(register int c, register int s[]){
    while (*s >= 0) {
	if(*s == c) return YES;
	s++;
    }
    return NO;
}
char STRING_BUFFER[ MAXLEN ]; /* временный буфер */
/* Снять пометку с "горячей" клавиши.            */
char *MnuConvert (char *s, int *pos){
    int i = 0;
    *pos = (-1);
    while (*s) {
	if (*s == M_HOT) { *pos = i; s++; }
	else STRING_BUFFER[i++] = *s++;
    }
    STRING_BUFFER[i] = '\0'; return STRING_BUFFER;
}
/* Рамка вокруг окна с меню */
static void MnuWin (Menu *m) {
    WinBorder(m->win, m->bg_attrib, m->sel_attrib,
		      m->title, m->scrollok, YES);
}
/* Нарисовать scroll bar в нужной позиции */
static void MnuWinBar (Menu *m) {
    WINDOW *w = m -> win;  /* окно */
    WinScrollBar(m->win, m->scrollok, m->current, m->nitems,
		 m->title, m->bg_attrib);
    if(m->scrollBar)  /* может быть еще какие-то наши действия */
       m->scrollBar(m, m->current, m->nitems);
}
/* Роллирование меню */
/*
	+---+----->+-МАССИВ--+<-----+
	|  n|всего |;;;;;;;;;|      | shift сдвиг до окна
     cur|   |      |;;;;;;;;;|      |
 текущий|   |   =ОКНО============<---------|
 элемент|   |   I   ;;;;;;;;;   I   | y строка окна
 0..n-1 |   |   I   ;;;;;;;;;   I   |      |
	+------>I###:::::::::###I<--+      |h высота окна
	    |   I   ;;;;;;;;;   I          |
	    |   =================<---------+
	    |      |;;;;;;;;;|
	    +----->|_________|
*/
static void MnuRoll (Menu *ptr,
    int aid,     /* какой новый элемент выбрать (0..n-1) */
    int *cur, int *shift,
    int h,       /* высота окна    (строк)      */
    int n,       /* высота items[] (элементов)  */
    void (*go)   (Menu *p, int y, int eraseOld),
    void (*draw) (Menu *p),
    int DY
) {
    int     y = *cur - *shift;	/* текущая строка окна */
    int     newshift;		/* новый сдвиг */
    int     AID_UP, AID_DN;
    if (aid < 0 || aid >= n) return;  /* incorrect */
    if (y   < 0 || y   >= h) return;  /* incorrect */
    AID_UP = MIN (DY, n);
    AID_DN = MAX (0, MIN (n, h - 1 - DY));
    if (aid < *cur && y <= AID_UP && *shift > 0)
	goto scroll;		/* down */
    if (aid > *cur && y >= AID_DN && *shift + h < n)
	goto scroll;		/* up */
    if (*shift <= aid && aid < *shift + h) {
    /* роллировать не надо, а просто пойти в нужную строку окна */
	(*go) (ptr, aid - *shift, YES);
	*cur = aid;      /* это надо изменять ПОСЛЕ (*go)() !!! */
	return;
    }
scroll:
    if      (aid > *cur)   newshift = aid - AID_DN; /* вверх up   */
    else if (aid < *cur)   newshift = aid - AID_UP; /* вниз  down */
    else                   newshift = *shift;
    if (newshift + h > n)  newshift = n - h;
    if (newshift < 0)      newshift = 0;
    *shift = newshift; *cur = aid;
    (*draw) (ptr); /* перерисовать окно */
    (*go)   (ptr, aid - newshift, NO); /* встать в нужную строку окна */
}
/* Инициализация и разметка меню. На входе:
	m->items       Массив строк.
	m->title       Заголовок  меню.
	m->top         Верхняя строка окна (y).
	m->left        Левый край (x).
	m->handler     Обработчик нажатия клавиш или NULL.
	m->hitkeys     Специальные клавиши [] или NULL.
	m->bg_attrib   Цвет фона окна.
	m->sel_attrib  Цвет селекции.
*/
int MnuInit (Menu *m) {
    int len, pos; char *s; register i;
    m -> current  = m -> shift = 0;
    m -> scrollok = m -> key = 0;
    if (m -> hotkeys) { /* уничтожить старые "горячие" ключи */
	free ((char *) m -> hotkeys); m -> hotkeys = (int *) NULL;
    }
 /* подсчет элементов меню */
    for (i = 0; M_ITEM (m, i) != (char *) NULL; i++);
    m -> nitems = i;
 /* отвести массив для "горячих" клавиш */
    if (m -> hotkeys = (int *) malloc (sizeof (int) * m -> nitems)) {
	for (i = 0; i < m -> nitems; i++)
	    m -> hotkeys[i] = NOKEY;
    }
 /* подсчитать ширину текста */
    len = m -> title ? strlen (m -> title) : 0;
    for (i = 0; i < m -> nitems; i++) {
	if (*(s = M_ITEM (m, i)) == M_CTRL) continue;
	s = MnuConvert (s, &pos);
	if (m -> hotkeys && pos >= 0)
	    m -> hotkeys[i] =
		isupper (s[pos]) ? tolower (s[pos]) : s[pos];
	if ((pos = strlen (s)) > len)
	    len = pos;
    }
 /* сформировать окно */
#define BORDERS_HEIGHT (2 +        (m -> title    ? 2 : 0))
#define BORDERS_WIDTH  (2 + 2*DX + (m -> scrollok ? BARWIDTH + 1 : 0))
    m -> height = m->nitems + BORDERS_HEIGHT;
    if (m -> height > LINES * 2 / 3) { /* слишком высокое меню */
	m -> scrollok = BAR_VER;       /* будет роллироваться  */
	m -> height = LINES * 2 / 3;
    }
    if((m -> width = len + BORDERS_WIDTH) > COLS ) m->width = COLS;
    m -> textheight = m->height - BORDERS_HEIGHT;
    m -> textwidth  = m->width  - BORDERS_WIDTH;
 /* окно должно лежать в пределах экрана */
    if( m->top  + m->height > LINES ) m->top  = LINES - m->height;
    if( m->left + m->width  > COLS  ) m->left = COLS  - m->width;
    if( m->top  < 0 ) m->top  = 0;
    if( m->left < 0 ) m->left = 0;
    if( m->win ){ /* уничтожить старое окно */
	KillWin( m->win ); m->win = NULL; }
    if( m->win == NULL ){ /* создать окно и нарисовать основу */
	if((m->win =  newwin(m->height, m->width, m->top, m->left))
		   == NULL) return 0;
	keypad(m->win, TRUE); MnuWin(m); MnuDraw(m);
	/* но окно пока не вставлено в список активных окон */
    }
    return ( m->win != NULL );
}
/* Деинициализировать меню */
void MnuDeinit (Menu *m) {
    if( m->win ){ KillWin (m->win); m->win = NULL; }
    if( m->hotkeys ){
	free ((char *) m -> hotkeys); m -> hotkeys = (int *) NULL;
    }
}
/* Спрятать меню */
void MnuHide (Menu *m){ if( m->win ) HideWin(m->win); }
/* Зачистить место для line-той строки окна меню */
static void MnuBox (Menu *m, int line, int attr) {
    register    WINDOW *w = m -> win;
    register    i, xend   = MXEND(m);
    wattrset (w, attr);
    for (i = 1; i < xend; i++)
	mvwaddch (w, line, i, ' ');
    /* ликвидировать последствия M_CTRL-линии */
    wattrset (w, m->bg_attrib);
    mvwaddch (w, line, 0,    VER_LINE);
    mvwaddch (w, line, xend, VER_LINE);
    wattrset (w, m->bg_attrib);
}
/* Нарисовать строку меню в y-ой строке окна выбора */
void MnuDrawItem (Menu *m, int y, int reverse, int selection) {
    register WINDOW *w = m -> win;
    int     pos, l, attr;
    int     ay = WY (m->title, y), ax = WX (0);
    char   *s, c;
    int     hatch, bold, label, cont = NO, under;
    if (y + m -> shift >= 0 && y + m -> shift < m -> nitems) {
	s =    M_ITEM (m, y + m -> shift);
	hatch = M_TST (m, y + m -> shift, I_NOSEL) ||
		M_TST (m, y + m -> shift, M_HATCH);
	bold  = M_TST (m, y + m -> shift, M_BOLD);
	label = M_TST (m, y + m -> shift, M_LABEL);
	under = M_TST (m, y + m -> shift, I_EXE);
    }
    else {  /* строка вне допустимого диапазона */
	s = "~"; label = hatch = bold = NO;
    }
    if (*s == M_CTRL) { /* нарисовать горизонтальную черту */
	int x, xend = MXEND(m);
	wattrset(w, m->bg_attrib);
	for(x=1; x < xend; x++)
		mvwaddch(w, ay, x, HOR_LINE);
	mvwaddch (w, ay, 0,    LEFT_JOIN);
	mvwaddch (w, ay, xend, RIGHT_JOIN);
	wattrset (w, m->bg_attrib);
	return;
    }
    l = strlen(s = MnuConvert (s, &pos));
    c = '\0';
    if (l > m -> textwidth) { /* слишком длинная строка */
	c = s[m -> textwidth];
	s[m -> textwidth] = '\0'; cont = YES;
	if (pos > m -> textwidth) pos = (-1);
    }
    if (selection)
	MnuBox (m, ay, reverse ? m->sel_attrib   : m->bg_attrib);
    wattrset (w, attr = (bold    ? A_BOLD        : 0) |
			(hatch   ? A_ITALICS     : 0) |
			(under   ? A_UNDERLINE   : 0) |
			(reverse ? m->sel_attrib : m->bg_attrib));
    mvwaddstr (w, ay, ax, s);
    if( cont ) mvwaddch(w, ay, ax+m->textwidth, RIGHT_TRIANG);
 /* Hot key letter */
    if (pos >= 0) {
	wattron (w, bold ? A_ITALICS : A_BOLD);
	mvwaddch (w, ay, WX(pos), s[pos]);
    }
    if (label){  /* строка помечена */
	wattrset (w, attr | A_BOLD);
	mvwaddch (w, ay, 1, LABEL);
    }
    if (under){
	wattrset (w, A_BOLD);
	mvwaddch (w, ay, ax-1, BOX_HATCHED);
    }
    if (c) s[m->textwidth] = c;
    wattrset (w, m->bg_attrib);
    SetPoint (m->savep, ay, ax-1);  /* курсор поставить перед словом */
}
/* Выбор в меню подходящего элемента */
int MnuNext (Menu *m) {
    char *s; register y = m -> current;
    for (++y; y < m -> nitems; y++)
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	 return y;
    return (-1);
}
int MnuPrev (Menu *m) {
    char *s; register y = m -> current;
    for (--y; y >= 0; --y)
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	 return y;
    return (-1);
}
int MnuPgUp (Menu *m) {
    char *s; register n, y = m -> current;
    for (--y, n = 0; y >= 0; --y) {
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	  n++;
      if (n == m -> textheight) return y;
    }
    return MnuFirst (m);
}
int MnuPgDn (Menu *m) {
    char *s; register n, y = m -> current;
    for (++y, n = 0; y < m -> nitems; y++) {
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	 n++;
      if (n == m -> textheight) return y;
    }
    return MnuLast (m);
}
int MnuFirst (Menu *m) {
    char *s; register y;
    for (y = 0; y < m -> nitems; y++)
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	 return y;
    return (-1);
}
int MnuLast (Menu *m) {
    char *s; register y;
    for (y = m -> nitems - 1; y >= 0; --y)
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	 return y;
    return (-1);
}
int MnuThis (Menu *m) {
    char *s;
    if (m -> current < 0 || m -> current >= m -> nitems)
	return (-1);		/* error */
    if ((s = M_ITEM (m, m -> current)) &&
	 *s != M_CTRL && !M_TST (m, m -> current, I_NOSEL))
	return m -> current;
    return (-1);
}
int MnuName (Menu *m, char *name) {
    char *s; register y; int pos;
    for(y = 0; y < m -> nitems; ++y)
      if ((s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL) &&
	   strcmp(name, MnuConvert(s, &pos)) == 0 ) return y;
    return (-1);
}
int MnuHot (Menu *m, unsigned c) {
    register y; char *s;
    if (m -> hotkeys == (int *) NULL)
	return (-1);
    if (c < 0400 && isupper (c))
	c = tolower (c);
    for (y = 0; y < m -> nitems; y++)
	if (c == m -> hotkeys[y] &&
	   (s = M_ITEM (m, y)) && *s != M_CTRL && !M_TST (m, y, I_NOSEL))
	    return y;
    return (-1);
}
/* Нарисовать содержимое меню для выбора */
void MnuDraw (Menu *m) {
    register    i, j;
    for (i = 0; i < m -> textheight; i++)
	MnuDrawItem (m, i, NO, m -> scrollok ? YES : NO);
}
/* Поставить курсор в line-тую строку окна. */
void MnuPoint(Menu *m, int line,
	      int eraseOld /* стирать старую селекцию? */){
    int curline = m->current - m->shift; /* текущая строка окна */
    if (line < 0 || line >= m -> textheight) return;  /* ошибка */
    if (eraseOld && curline != line) /* стереть старый выбор    */
	MnuDrawItem (m, curline, NO, YES);
    MnuDrawItem (m, line, YES, YES); /* подсветить новую строку */
}
/* Перейти к y-той строке массива элементов, изменить картинку  */
void MnuPointAt (Menu *m, int y) { char *s;
    if (y < 0 || y >= m->nitems) return; /* ошибка! */
    if ((s = M_ITEM (m, y)) == NULL || *s == M_CTRL) return;
    MnuRoll (m, y, &m -> current,    &m -> shift,
		    m -> textheight,  m -> nitems,
	     MnuPoint, MnuDraw, MNU_DY);
    if (m -> scrollok) MnuWinBar(m); /* сдвинуть scroll bar */
    GetBack(m->savep, m->win); /* вернуть курсор в начало строки селекции,
				* откуда он был сбит MnuWinBar-ом */
}
/* Выбор в меню без участия "мыши". */
int MnuUsualSelect (Menu *m, int block) {
    int sel, snew, c, done = 0;
    m -> key = (-1);
    if( ! m->win ) return TOTAL_NOSEL;
    if((sel = MnuThis  (m)) < 0)
    if((sel = MnuFirst (m)) < 0)
	return TOTAL_NOSEL; /* в меню нельзя ничего выбрать */
    RaiseWin   (m->win);    /* сделать окно верхним         */
    MnuPointAt (m, sel);    /* проявить */
    if(m->showMe) m->showMe(m);  /* может быть изменить позицию ? */
    for (;;) {
	c = WinGetch (m->win);
INP:
	if (m -> hitkeys && m -> handler) {
	    HandlerReply reply;
	    if (is_in (c, m -> hitkeys)) {
		c = (*m -> handler) (m, c, &reply);
	    /* восстановить scroll bar */
		MnuPointAt (m, m -> current);
		switch (reply) {
		    case HANDLER_CONTINUE:     continue;
		    case HANDLER_NEWCHAR:      goto INP;
		    case HANDLER_OUT:          goto out;
		    case HANDLER_SWITCH:       default:
			break;	/* goto switch(c) */
		}
	    }
	}
	switch (c) {
	    case KEY_UP:
		if ((snew = MnuPrev (m)) < 0)  break;
		goto mv;
	    case KEY_DOWN:
	next:
		if ((snew = MnuNext (m)) < 0)  break;
		goto mv;
	    case KEY_HOME:
		if ((snew = MnuFirst (m)) < 0) break;
		goto mv;
	    case KEY_END:
		if ((snew = MnuLast (m)) < 0)  break;
		goto mv;
	    case KEY_NPAGE:
		if ((snew = MnuPgDn (m)) < 0)  break;
		goto mv;
	    case KEY_PPAGE:
		if ((snew = MnuPgUp (m)) < 0)  break;
		goto mv;
	    case KEY_IC:   /* поставить/снять пометку */
		if (M_TST (m, sel, M_LABEL)) M_CLR (m, sel, M_LABEL);
		else                         M_SET (m, sel, M_LABEL);
		MnuPointAt (m, sel);
	    /* Если вы вычеркнете  goto next;
	     * и оставите просто   break;
	     * то вставьте в это место
	     * MnuPoint( m, m->current - m->shift, NO ); */
		goto next;
	    case KEY_DC:
		if (M_TST (m, sel, M_HATCH)) M_CLR (m, sel, M_HATCH);
		else                         M_SET (m, sel, M_HATCH);
		MnuPointAt (m, sel); goto next;
	    case KEY_LEFT:
		if (block & M_LFT) {
		    sel = M_LEFT;  goto out;
		} break;
	    case KEY_RIGHT:
		if (block & M_RGT) {
		    sel = M_RIGHT; goto out;
		} break;
	    case 0: break;
	    default:
		if (c == '\n' || c == '\r' || c == ESC)
		    goto out;
		if ((snew = MnuHot (m, c)) < 0) {
		    beep(); break;
		}
	    /* иначе найден HOT KEY (горячая клавиша) */
		done++; goto mv;
	}
	continue;
mv:
	MnuPointAt (m, sel = snew);
	if(done){ wrefresh(m->win); /* проявить новую позицию */ break; }
    }
out: wnoutrefresh(m->win);
     return((m->key = c) == ESC ? -1 : sel);
     /* Меню автоматически НЕ ИСЧЕЗАЕТ: если надо
      * явно делайте MnuHide(m); после MnuUsualSelect(); */
}

© Copyright А. Богатырев, 1992-95
Си в UNIX

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