Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 78 79 80 81 82 83 84  85 86 87
        char valid;       /* существует ли этот каталог вообще */
        short readErrors; /* != 0, если каталог не читается    */
} DirContents;
     /* Виды сортировки имен в каталоге */
typedef enum { SORT_ASC, SORT_DESC, SORT_SUFX,
               SORT_NOSORT, SORT_SIZE }         Sort;
extern Sort sorttype; extern int in_the_root;

int   gcmps (const void *p1, const void *p2);
Info *blkcpy(Info *v); void blkfree(Info *v);
Info *glob(char **patvec,  char *dirname);
Info *glb(char   *pattern, char *dirname);
int ReadDir(char *dirname, DirContents *d);

struct savech{ char *s, c; };
#define SAVE(sv, str) (sv).s = (str); (sv).c = *(str)
#define RESTORE(sv) if((sv).s)   *(sv).s = (sv).c

/* _______________________ файл glob.c __________________________ */
#include "glob.h"
int in_the_root = NO;        /* читаем корневой каталог ?     */
Sort sorttype = SORT_SUFX;   /* сортировка имен по суффиксу   */
Info NullInfo = { NULL, 0 }; /* и прочие поля = 0 (если есть) */

char *strdup(const char *s){
   char *p = malloc(strlen(s)+1); if(p)strcpy(p, s); return p; }

/* Содержится ли любой из символов в строке ? */
int any(register char *s, register char *p){
   while( *s ){ if( strchr(p, *s)) return YES; s++; }
   return NO;
}
/* Найти последнюю точку в имени */
static char *lastpoint (char *s)
{   register char *last; static char no[] = "";
    if((last = strchr(s, '.')) == NULL) return no;
    /* если имя начинается с точки - не считать ее */
    return( last == s ? no : last );
}
/* Сравнение строк с учетом их суффиксов */
int strsfxcmp (register char *s1, register char *s2){
    char *p1, *p2, c1, c2; int code;
    p1 = lastpoint (s1); p2 = lastpoint (s2);
    if (code = strcmp (p1, p2)) return code; /* суффиксы разные */
    /* иначе: суффиксы равны. Сортируем по головам              */
    c1 = *p1; c2 = *p2; *p1 = '\0'; *p2 = '\0'; /* временно     */
    code = strcmp (s1, s2);
    *p1 = c1; *p2 = c2; return code;
}
/* Функция сортировки */
int gcmps(const void *p1, const void *p2){
    Info *s1 = (Info *) p1, *s2 = (Info *) p2;
    switch( sorttype ){
    default:
    case SORT_ASC:    return    strcmp(s1->s, s2->s);
    case SORT_DESC:   return   -strcmp(s1->s, s2->s);
    case SORT_SUFX:   return strsfxcmp(s1->s, s2->s);
    case SORT_NOSORT: return (-1);
#ifdef FILF
    case SORT_SIZE:   return (s1->size <  s2->size ? -1 :
                              s1->size == s2->size ? 0 : 1 );
#endif
    }
}
/* Копирование блока */
Info *blkcpy(Info *v){
    register i, len;
    Info *vect = (Info *) malloc(((len=blklen(v)) + 1) * sizeof(Info));
    for(i=0; i < len; i++ ) vect[i] = v[i];
    vect[len] = NullInfo;   return vect;
}
/* Измерение длины блока */
int blklen(Info *v){
    int i = 0;
    while( v->s ) i++, v++;
    return i;
}
/* Очистка блока (уничтожение) */
void blkfree(Info *v){
     Info *all = v;
     while( v->s )
            free((char *) v->s ), v++;
     free((char *) all );
}
/* Сравнение двух блоков */
int blkcmp( register Info *p, register Info *q ){
    while( p->s && q->s && !strcmp(p->s, q->s) &&
          (p->fl & I_SYS) == (q->fl & I_SYS)){ p++; q++; }
    if( p->s == NULL && q->s == NULL )
        return 0;       /* совпадают   */
    return 1;           /* различаются */
}
char   globchars [] = "*?[";
Info gargv[MAX_ARGV]; int gargc;
static short readErrors;
void greset() { gargc = 0; readErrors = 0; }

/* Расширить шаблон имен файлов в сами имена */
static void globone(char *pattern, char dirname[]){
     extern char *strdup(); struct stat st;
     DIR *dirf; struct dirent *d;
     if( any(pattern, globchars) == NO ){  /* no glob */
             gargv[gargc]   = NullInfo;
             gargv[gargc].s = strdup(pattern);
             gargc++;
             gargv[gargc]   = NullInfo;
             return;
     }
     if((dirf = opendir(dirname)) == NULL){ readErrors++; goto out; }
     while(d = readdir(dirf)){
       if(match(d->d_name, pattern)){
          char fullname[512];
          if( sorttype != SORT_NOSORT && !strcmp(d->d_name, "."))
              continue;
          /* В корневом каталоге имя ".." следует пропускать */
          if( in_the_root && !strcmp(d->d_name, "..")) continue;
          /* Проверка на переполнение */
          if( gargc == MAX_ARGV - 1){
              free(gargv[gargc-1].s);
              gargv[gargc-1].s  = strdup(" Слишком много файлов!!!");
              gargv[gargc-1].fl = I_SYS;
              break;
          }
          gargv[gargc]     = NullInfo;
          gargv[gargc].s   = strdup(d->d_name);
          sprintf(fullname, "%s/%s", dirname, d->d_name);
          if(stat(fullname, &st) < 0) gargv[gargc].fl |= I_NOSEL;
          else if(isdir(st))          gargv[gargc].fl |= I_DIR;
          else if(isexe(st))          gargv[gargc].fl |= I_EXE;
#ifdef FILF
          gargv[gargc].size = st.st_size;
          gargv[gargc].uid  = st.st_uid;
          gargv[gargc].gid  = st.st_gid;
          gargv[gargc].mode = st.st_mode;
#endif
          gargc++;
       }
     }
     closedir(dirf);
out: gargv[ gargc ] = NullInfo;
}
/* Расширить несколько шаблонов */
Info *glob(char **patvec, char *dirname){
      greset();
      while(*patvec){ globone(*patvec, dirname); patvec++; }
      qsort(gargv, gargc, sizeof(Info), gcmps);
      return blkcpy(gargv);
}
Info *glb(char *pattern, char *dirname){ char *pv[2];
      pv[0] = pattern; pv[1] = NULL; return glob(pv, dirname);
}
/* Прочесть содержимое каталога, если оно изменилось:
 * Вернуть: 0  - каталог не менялся;
 *          1  - изменился;
 *       1000  - изменился рабочий каталог (chdir);
 *          -1 - каталог не существует;
 */
int ReadDir(char *dirname, DirContents *d){
    struct stat st; Info *newFiles;
    int save = YES; /* сохранять метки у файлов ? */
    int dirchanged = NO; /* сделан chdir() ? */

    /* каталог мог быть удален, а мы об этом не извещены */
    if( stat(dirname, &st) < 0 ){
        d->valid = NO; d->lastRead = 0L;
        if(d->files) blkfree(d->files);
        d->files = blkcpy( &NullInfo );
        return (-1); /* не существует */
    } else d->valid = YES;
    /* не изменился ли адрес каталога, хранимого в *d ? */
    if(d->ino != st.st_ino || d->dev != st.st_dev){ /* изменился */
       d->ino  = st.st_ino;   d->dev  = st.st_dev;
       save = NO; d->lastRead = 0L; dirchanged = YES;
    }
    /* не изменилось ли имя каталога ? */
    if( !d->name || strcmp(d->name, dirname)){
        if(d->name) free(d->name); d->name = strdup(dirname);
        /* save=NO; d->lastRead = 0; */
    }
    /* проверим, был ли модифицирован каталог ? */
    if( save==YES && d->files && st.st_mtime == d->lastRead )
        return 0;       /* содержимое каталога не менялось */
    d->lastRead = st.st_mtime;
    newFiles = glb("*", d->name);  /* прочесть содержимое каталога */
    if(save == YES && d->files){
        register Info *p, *q;
        if( !blkcmp(newFiles, d->files)){
             blkfree(newFiles); return 0;  /* не изменилось */
        } /* иначе сохранить пометки */
        for(p= d->files; p->s; p++)
          for(q= newFiles; q->s; ++q)
            if( !strcmp(p->s, q->s)){
                q->fl |= p->fl & ~I_SYS;   break;
            }
    }
    if(d->files) blkfree(d->files);
    d->files = newFiles; d->readErrors = readErrors;
    return 1 + (dirchanged ? 999:0);
    /* каталог изменился */
}

                   /*      Пример 19      */
/* ________________________файл menu.h __________________________ */
/*                     РОЛЛИРУЕМОЕ МЕНЮ                           */
/* _______________________________________________________________*/
#include              
#include              
#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 
/* ---------------- implementation module ------------------------- */
/* Не входит ли символ в специальный набор? Массив завершается (-1) */
int is_in(register int c, register int s[]){
Предыдущая страница Следующая страница
1 ... 78 79 80 81 82 83 84  85 86 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама