Сайт | Скачать | Видео | Wiki

Автор Тема: Построитель меню JWM на C  (Прочитано 4346 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM на C
« : 02 Февраль 2016, 15:19:49 »
Очень упрощённый аналог ls, вводит список файлов *.desktop
#include <stdio.h>
#include <dirent.h>
#include <string.h>

int main() {
    DIR *dir;
    struct dirent *entry;

    dir = opendir("/usr/share/applications");
    if (!dir) {
        perror("diropen");
    }

    while ((entry = readdir(dir)) != NULL) {
if ( strstr(entry->d_name, ".desktop")!=0 ) {
         printf(entry->d_name);
         printf("\n");
}
    }

    closedir(dir);
}
Думаю приспособить для fixmenus.
« Последнее редактирование: 23 Февраль 2016, 07:52:32 от sfs »
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Оффлайн sfs

  • Администратор
  • Ветеран
  • *****
  • Сообщений: 17516
  • Репутация: +137/-0
    • PuppyRus-A
Построитель меню JWM
« Ответ #1 : 02 Февраль 2016, 15:29:53 »
На выходе получается ускорение по сравнению с sh ? Смысл в этом?

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #2 : 02 Февраль 2016, 17:53:08 »
На выходе получается ускорение по сравнению с sh ?
Должно
Смысл в этом?
Расти над самим собой.
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Оффлайн dim-kut

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 1016
  • Репутация: +41/-0
Построитель меню JWM
« Ответ #3 : 02 Февраль 2016, 18:02:00 »
На выходе получается ускорение по сравнению с sh ?
Должно
Должно, но на современных компах мы можем этого не заметить.
Смысл в этом?
Расти над самим собой.
+1
Engineering is the art of making what you want from things you can get.
Мои модули для PRA64fat лежат здесь. Под 64light могут не заработать.
Мой блог - dim-kut.livejournal.com Фонд, которому я доверяю - pomogi.org

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #4 : 03 Февраль 2016, 10:20:57 »
 Научил lsapplications понимать Categories:# ./lsapplications1
Категория?
# ./lsapplications1 Network
Linux-Firewall.desktop
Pure_FTPd-FTP-server.desktop
gpptp.desktop
mtr-traceroute.desktop
pnethood.desktop
tsclient.desktop
wifi.desktop
CMake.desktop
Осталось сделать вывод в нужном формате.
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #5 : 04 Февраль 2016, 18:23:26 »
 Я забуксовал. Этот вариант:
#include <stdio.h>
#include <dirent.h>
#include <string.h>

DIR *dir;
FILE *fp;
char buf[64], str[1024];
char *name, *icon, *exec;
char *appdir="/usr/share/applications/";

struct dirent *entry;

int main(int argc, char *argv[]) {
if (argc<2) {
printf("Категория? %s","\n");
return 0;
}
    dir = opendir(appdir);
    if (!dir) {
        perror("diropen");
    }
printf("<JWM>%s","\n");
    while ((entry = readdir(dir))!=0) {
if (strstr(entry->d_name,".desktop")!=0 ) {
buf[0]=0;
strcat(buf,appdir);
strcat(buf,entry->d_name);
        fp=fopen(buf,"r");
        while (fgets(str,sizeof(str),fp)!=0) {
if (strstr(str,argv[1])!=0) {
while (fgets(str,sizeof(str),fp)!=0) {
name=strstr(str,"Name");
// *strchr(strchr(name, '=') + 1, '\n') = 0;
// name=("%s\n", strchr(name, '=') + 1);
}
while (fgets(str,sizeof(str),fp)!=0) {
icon=strstr(str,"Icon");
}
while (fgets(str,sizeof(str),fp)!=0) {
exec=strstr(str,"Exec");
}
printf("\t<Program %s%s%s %s%s%s%s%s%s","label=\"",name,"\"","icon\"",icon,"\">",exec,"</Program>","\n");
}

}
        fclose(fp);
}

    }
    closedir(dir);
    printf("<JWM>%s","\n");
}
генерирует подменю заданной категории но не полностью, без icon и exec. Не желает брать переменные.
<JWM>
<Program label="Name=Partview view partition sizes
" icon"(null)">(null)</Program>
<Program label="Name=Xfdiff-cut
" icon"(null)">(null)</Program>
<Program label="Name=gFnRename
" icon"(null)">(null)</Program>
<Program label="Name=Gcolor2
" icon"(null)">(null)</Program>
<Program label="Name=Сохранить настройки в sfs
" icon"(null)">(null)</Program>
<Program label="ies=GTK;GNOME;Application;Utility;
" icon"(null)">(null)</Program>
<Program label="Name=PTM Timer
" icon"(null)">(null)</Program>
<Program label="Name=puppyPDF convert file to PDF
" icon"(null)">(null)</Program>
<Program label="(null)" icon"(null)">(null)</Program>
<Program label="Name=ePDFView PDF viewer
" icon"(null)">(null)</Program>
<Program label="Name=mtPaint-snapshot screen capture
" icon"(null)">(null)</Program>
<JWM>
Закомментированный код убирает "Name=" но вызывает сегментацию. Что делать  ???
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Оффлайн ander

  • Активный участник
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +16/-0
Построитель меню JWM
« Ответ #6 : 04 Февраль 2016, 23:15:40 »
*strchr(strchr(name, '=') + 1, '\n') = 0;Еще скобок не хватает:
*(strchr(strchr(name, '=') + 1, '\n')) = 0;без них эта конструкция пытается записать ноль даже сразу и не соображу куда, но явно не по возвращаемому функцией указателю, скорее по адресу самой функции, где она в памяти располагается.

А конструкция name=("%s\n", strchr(name, '=') + 1); вообще непонятная.  Может тут sprintf предполагался?

А переменные равны null, все правильно.
Смотрите, что получается.  Начался while (fgets(str,sizeof(str),fp)!=0) {}, он же переберет все строки, для каждой выполняя name=strstr(str,"Name");.  Тут, видимо, повезло и "Name" нашлось в последней строке, поэтому name установлен. А последующие while не выполняются вовсе, поскольку fgets() читать больше нечего, файл-то уже кончился.  Вот icon и exec никуда и не указывают.

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #7 : 05 Февраль 2016, 09:25:45 »
*strchr(strchr(name, '=') + 1, '\n') = 0;Еще скобок не хватает:
*(strchr(strchr(name, '=') + 1, '\n')) = 0;без них эта конструкция пытается записать ноль даже сразу и не соображу куда, но явно не по возвращаемому функцией указателю, скорее по адресу самой функции, где она в памяти располагается.
А конструкция name=("%s\n", strchr(name, '=') + 1); вообще непонятная.  Может тут sprintf предполагался?
Эту конструкцию я "честно стырил" на одном из форумов. В первоисточнике было printf. Можно сделатьname=strchr(name, '=') + 1;но тогда строка "ломается" и всё равно "ошибка сегментации".
А последующие while не выполняются вовсе, поскольку fgets() читать больше нечего, файл-то уже кончился.  Вот icon и exec никуда и не указывают.
Это понятно, но как заставить fgets перечитать файл?
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Оффлайн ander

  • Активный участник
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +16/-0
Построитель меню JWM
« Ответ #8 : 05 Февраль 2016, 11:35:42 »
Перечитать можно сделав rewind или fseek, но логичнее было бы все поиски делать в одном цикле.  И тут еще один прикол - все эти name - это просто указатели на ячейку памяти, строк они не содержат.  Если они указывают куда-то, где располагается массив str и в этом массиве действительно есть строка по этому адресу, то все нормально, можно прочитать эту строку через name.  Но ведь на следующем проходе цикла while массив str будет содержать уже другие данные, а name указывает на прежнее место, то есть напечатав его значение, вы увидите совсем не то, что на предыдущем проходе, хотя сам name и не изменялся.
В C вообще часто нужно четко представлять, как байты в памяти располагаются и указатели на них указывают.

Оффлайн k0l0p0k

  • Ветеран
  • *****
  • Сообщений: 568
  • Репутация: +7/-0
Построитель меню JWM
« Ответ #9 : 05 Февраль 2016, 11:43:15 »
Цитировать
Это понятно, но как заставить fgets перечитать файл?

1)см выше :) . rewind или fseek
2)костыльнее - закрыть файл, открыть заново
3)считать строки в массив и  работать уже с массивом
ну или файл в память считать, массив все равно нужен будет - указатели на строки хранить.
...
« Последнее редактирование: 05 Февраль 2016, 11:48:39 от k0l0p0k »
1.нетбук  Samsung N145 (оси: Минт17.PRA-midle)
2.стационары  (core-i3,4-16Gb,Radeon R9 280X,Минт17,PRA)

Оффлайн ander

  • Активный участник
  • Старожил
  • ****
  • Сообщений: 300
  • Репутация: +16/-0
Построитель меню JWM
« Ответ #10 : 05 Февраль 2016, 13:52:34 »
примерно так.  Не оптимально, повторения в функцию надо вынести, но работает.
#include <stdio.h>
#include <dirent.h>
#include <string.h>

DIR *dir;
FILE *fp;
char buf[64], str[1024], namestr[64], iconstr[64], execstr[64];
char *tpoint, *lf;
int category_found;
char *appdir="/usr/share/applications/";
        
struct dirent *entry;

int main(int argc, char *argv[]) {
        if (argc<2) {
                printf("Категория?\n");
                return 0;
        }
    dir = opendir(appdir);
    if (!dir) {
        perror("diropen");
    }
    namestr[64]=iconstr[64]=execstr[64]=0; /* чтоб в любом случае в конце строки был */
        printf("<JWM>\n");
    while ((entry = readdir(dir))!=0) {
                if (strstr(entry->d_name,".desktop")!=0 ) {
                        buf[0]=0;
                        strcat(buf,appdir);
                        strcat(buf,entry->d_name);
                fp=fopen(buf,"r");
                category_found=0;
                while (fgets(str,sizeof(str),fp)!=0) {
                                if ( (lf=strchr(str, '\n'))!=0 ) *lf=0;  /* убрали перевод строки, чтобы не болтался*/
                                if (strstr(str,argv[1])!=0) category_found=1;
                                else if ((tpoint=strstr(str,"Name="))!=0) strncpy(namestr, strchr(tpoint, '=')+1, sizeof(namestr)-1); /* найденную строку сохранили */
                                else if ((tpoint=strstr(str,"Icon"))!=0) strncpy(iconstr, strchr(tpoint, '=')+1, sizeof(iconstr)-1);
                                else if ((tpoint=strstr(str,"Exec"))!=0) strncpy(execstr, strchr(tpoint, '=')+1, sizeof(execstr)-1);
                        }
                        if (category_found) printf("\t<Program label=\"%s\" icon\"%s\">%s</Program>\n", namestr, iconstr, execstr);
                        fclose(fp);
                }
    }
    closedir(dir);
    printf("<JWM>\n");
    return 0;
}
Чего-то отступы при вставке сбиваются, с табуляцией видимо проблемы.  Но принцип в общем то понятен, я думаю.
« Последнее редактирование: 05 Февраль 2016, 14:02:15 от ander »

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #11 : 05 Февраль 2016, 14:02:05 »
 Благодарю! Сейчас буду допиливать.
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Оффлайн k0l0p0k

  • Ветеран
  • *****
  • Сообщений: 568
  • Репутация: +7/-0
Построитель меню JWM
« Ответ #12 : 05 Февраль 2016, 14:56:38 »
не возникнет ли проблем если длинна найденных строк превысит 64 ?
1.нетбук  Samsung N145 (оси: Минт17.PRA-midle)
2.стационары  (core-i3,4-16Gb,Radeon R9 280X,Минт17,PRA)

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #13 : 05 Февраль 2016, 15:05:11 »
не возникнет ли проблем если длинна найденных строк превысит 64 ?
Обрежет строку, но серьёзных проблем не будет, длинные строки могут быть label= и icon=, в exec - нет.
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c

Онлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 4897
  • Репутация: +135/-0
  • Старый чайник
Построитель меню JWM
« Ответ #14 : 06 Февраль 2016, 09:58:01 »
 Возникли проблемы. Например, при обработке файла Alsamixer-sound-mixer.desktop
[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=AlsaMixer -  аудио-микшер
Exec=xterm -e alsamixer

Icon=mini-sound.xpm
Categories=AudioVideo;

#MimeType=
Terminal=false
#GenericName=
#Comment=
#NoDisplay=
#Hidden=
#OnlyShowIn=
#NotShowIn=
#TryExec=
#Path=
#StartupNotify=true
#StartupWMClass=
В нём есть закомментированные строки с непрописанными параметрами в которых встречаются "Exec" и "Name". Программа запоминает последнее, пустое, значение. В результате получаем <JWM>
<Program label="" icon="mini-sound.xpm"></Program>
</JWM>
Если в цикл добавить строку while (fgets(str,sizeof(str),fp)!=0) {
if (str[1]=='#') continue;
она вырежет все закомментированные строки, но проблема "последнего значения" остаётся. Например GenericName, Name, Name[ru], Name[de] получим последнее, немецкое название, а надо Name[ru], которое никак не вставляется в код.
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk
Netbook Lenovo IdeaPad S10-3c