#include <gtk/gtk.h>
#include <string.h>
#include <stdio.h>
#include <wand/MagickWand.h>
#include <X11/extensions/Xrandr.h>
typedef struct{
gchar *filepath; //wallpaper image file path
gint timeout; //timeout count
gboolean savedefault; //savedefault flag
gboolean recovery; //recoveri flag
gboolean memtest; //memtest flag
gboolean playsound; //playsound flag
gboolean wallpaper; //wallpaper flag
gchar *resolution; //string-resolution
gint x_res; //x-resolution
gint y_res; //y-resolution
glong lfSize; //last file size
gchar *t_image_name;//temporary image-file name
gint x_preview; //width preview image
gint y_preview; //height preview image
gchar *work_file_buf;//file
gchar *file_buf; // buffers
} grub_config;
const gchar *STRING_1="Обращаю внимание!\n\
Утилита, изменяет файлы конфигурации загрузчика.\
В маловераятном случае но это может привести к потере \
операционной системой возможности нормально загружаться!\
Поэтому как говориться: все делаете на свой страх и риск!\
Начальный конфиг сохраняется в - /etc/default/grub_save\n\
Никакие изменения не вступают в силу вплоть до подтверждения \
выбранных настроек и ввода пароля!";
const gint file_path_len=1024;
const gint FilterCount=4;
const gchar *FileFilters[]={"*.jpg", "*.JPG", "*.png", "*.PNG"};
const gchar *logo_path="/usr/share/icons/hicolor/128x128/apps/grub-config.png"; // Иконка - лого
const gchar *DefaultImagePath="/usr/share/backgrounds"; // Дефолтная папка с обоями
const gchar *def_grub="/etc/default/grub"; // Конфиг Grub
const gchar *boot_img="/boot/grub/boot.jpg"; // Целевой файл обоев
const gchar *default_melody="480 900 2 1000 2 800 2 400 2 600 3"; // Мелодия бипа
const gint win_width=500, win_height=300; // Дефолтные размеры окна
const gint thumb_width=128, thumb_height=64;
const gint default_timeout=3;
//шаблоны поиска-замены-вставки
const gchar *tmpl1 = "GRUB_DEFAULT";
const gchar *tmpl2 = "GRUB_SAVEDEFAULT=true";
const gchar *tmpl3 = "GRUB_TIMEOUT";
const gchar *tmpl4 = "GRUB_DISABLE_LINUX_RECOVERY";
const gchar *tmpl4_1= "GRUB_DISABLE_RECOVERY";
const gchar *tmpl5 = "GRUB_GFXMODE";
const gchar *tmpl6 = "GRUB_BACKGROUND";
const gchar *tmpl7 = "GRUB_INIT_TUNE";
const gchar *tmpl8 = "memtest";
gchar *filepath=NULL, *save_filepath=NULL;
gchar *ScreenResolution=NULL;
GtkWidget *file_button, *color_button, *font_button, *thumb, *chkbx1, *chkbx[5], *button[4], *lebel[7], *spin_button, *resolution;
GtkWindow *main_window=NULL;
GtkFileFilter *GtkFilter=NULL;
GdkPixbuf *PixBuffer=NULL, *PixBuffer_logo=NULL;
GtkEntryBuffer *TextBufferRes=NULL;
grub_config grc;
void MessageBox(const gchar *message){
GtkWidget *dialog=gtk_message_dialog_new(main_window, \
GTK_DIALOG_MODAL, \
GTK_MESSAGE_INFO, \
GTK_BUTTONS_CLOSE, \
NULL);
gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), message);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
void MessError(const gchar *txt, const gchar *fn){
const gchar *caption="Error!\n";
GtkWidget *dialog;
int size=strlen(caption)+strlen(txt)+strlen(fn)+1;
gchar *buf=malloc(sizeof(gchar)*size);
sprintf(buf, "Error!\n%s %s", txt, fn);
dialog=gtk_message_dialog_new(main_window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, NULL);
gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), buf);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free(buf);
}
gboolean InputControl(){
const gchar *sr=gtk_entry_get_text(GTK_ENTRY(resolution));
memset(ScreenResolution, 0, 20*sizeof(gchar));
strcpy(ScreenResolution, sr);
const int max=9;
gchar sw[max], sh[max], tmp;
int i,w=0,h=0,res_x=0,res_y=0;
for(i=0; i<max; i++) sw[i]=sh[i]=0;
gboolean res=TRUE;
for(i=0; i<max; i++){
tmp=ScreenResolution[i];
if(tmp>='0' && tmp<='9')
if(res) sw[w++]=tmp;
else sh[h++]=tmp;
else if (tmp) res=FALSE;
}
if(res || w>4 || w<3 || h>4 || h<3) return FALSE;
w=0; h=0;
for(i=0; i<max; i++){
if(sw[i]) {res_x*=10; res_x+=(sw[i]-'0');}
if(sh[i]) {res_y*=10; res_y+=(sh[i]-'0');}
}
grc.x_res=res_x; grc.y_res=res_y;
strcpy(ScreenResolution, sw); strcat(ScreenResolution, "x"); strcat(ScreenResolution, sh);
grc.resolution=ScreenResolution;
gtk_entry_set_text(GTK_ENTRY(resolution), ScreenResolution);
return TRUE;
}
gchar *FileToBuffers(const gchar *filepath){
glong lSize, result;
FILE *pFile=fopen(filepath, "r");
if (pFile!=NULL){
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
g_print("opening file name: %s\n",filepath);
g_print("opening file size: %i\n",(int)lSize);
rewind (pFile);
gchar *buffer = g_malloc(sizeof(gchar)*lSize+1);
if (buffer == NULL) {fclose (pFile); g_free(buffer); return NULL;}
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fclose (pFile); g_free(buffer); return NULL;}
fclose (pFile);
grc.lfSize=lSize;
buffer[lSize]=0;
return buffer;
}
return NULL;
}
void ImageConvert(){ // Обработка изображения
#define ThrowWandException(wand) { char *description; ExceptionType severity; \
description=MagickGetException(wand,&severity); \
(void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \
description=(char *) MagickRelinquishMemory(description); grc.wallpaper=FALSE; exit(-1);}
if(!InputControl()) MessError("wrong input screen resolution","");
MagickBooleanType status;
MagickWand *magick_wand = NULL;
DrawingWand *d_wand = NULL;
PixelWand *p_wand = NULL;
MagickWandGenesis(); /* Read image file */
magick_wand=NewMagickWand();
status=MagickReadImage(magick_wand,grc.filepath);
if (status == MagickFalse) ThrowWandException(magick_wand);
MagickResetIterator(magick_wand); /* Resize image */
MagickResizeImage(magick_wand,grc.x_res,grc.y_res,LanczosFilter,1.0);
/* Write the image then destroy it. */
status=MagickWriteImages(magick_wand,grc.t_image_name,MagickTrue);
if (status == MagickFalse) ThrowWandException(magick_wand);
magick_wand=DestroyMagickWand(magick_wand);
if(d_wand) d_wand = DestroyDrawingWand(d_wand);
if(p_wand) p_wand = DestroyPixelWand(p_wand);
MagickWandTerminus();
}
gboolean my_strcmp(gchar *buf, const gchar *tpl){
gint i;
for(i=0; i<strlen(tpl); i++) if(buf[i]!=tpl[i]) return FALSE;
return TRUE;
}
int f_str(const gchar *tpl){ /* find string */
gint i, l=strlen(grc.file_buf);
for(i=0; i<l; i++) if(grc.file_buf[i]==tpl[0] && my_strcmp(grc.file_buf+i, tpl)) return i;
return 0;
}
int f_str_s(const gchar *tpl){ /*find line content string*/
int ptr=f_str(tpl);
if(!ptr) return 0;
while(grc.file_buf[ptr]!='\n') ptr--;
return ++ptr;
}
void s_move(gchar *dist, gchar *src, gint len){ // Перенос опред.колич.символов
gint i;
for(i=0; i<len; i++) dist[i]=src[i];
}
int next_l(gint ptr){
while(grc.file_buf[ptr]!='\n')
if(grc.file_buf[ptr]!='\0') ptr++;
else {
grc.file_buf[ptr++]='\n';
grc.file_buf[ptr]='\0';
return ptr;
}
return ++ptr;
}
gboolean add_str_aft_line(const gchar *tpl, gchar *new){ //добавление строки после найденной по шаблону
int ptr=f_str_s(tpl); //ищу строку по шаблону
if(!ptr) return FALSE; //выход если строка не найдена
ptr=next_l(ptr); //перевожу указатель на след.строку
s_move(grc.work_file_buf, grc.file_buf, ptr); //копирую текст до шаблона
grc.work_file_buf[ptr]='\0'; //завершаю нулем
strcpy(grc.work_file_buf+ptr, new); //вставляю новую строку
if(ptr<strlen(grc.file_buf)) //проверка на конец файла
strcat(grc.work_file_buf,grc.file_buf+ptr); //и копирую оставшееся
strcpy(grc.file_buf, grc.work_file_buf); //возвращаю результат в основной буфер
return TRUE;
}
gboolean facs(const gchar *tpl, gchar *new){ //поиск и замена строки
int ptr=f_str_s(tpl);
if(!ptr) return FALSE; //выход если строка не найдена
s_move(grc.work_file_buf, grc.file_buf, ptr); //копирую текст до шаблона
grc.work_file_buf[ptr]='\0'; //завершаю нулем
strcpy(grc.work_file_buf+ptr, new); //вставляю новую строку
ptr=next_l(ptr); //пареход на следующую строку в источнике
if(ptr<strlen(grc.file_buf)) //проверка на конец файла
strcat(grc.work_file_buf,grc.file_buf+ptr); //и копирую оставшееся
strcpy(grc.file_buf, grc.work_file_buf); //возвращаю результат в основной буфер
return TRUE;
}
gboolean get_line(gchar *buf, const gchar *tpl){//поиск строки содержащей шаблон и копирование её в буфер
gint ptr=f_str_s(tpl);
if(!ptr) return FALSE;
gint dptr=0;
while(grc.file_buf[ptr]!='\n' && grc.file_buf[ptr]!='\0') buf[dptr++]=grc.file_buf[ptr++];
buf[dptr]='\0';
if(!dptr) return FALSE;
return TRUE;
}
gboolean get_line_parameter_string(gchar *buf, const gchar *tpl){ //поиск строки по шаблону и возврат значения от знака = до первого пробела
if(!get_line(buf, tpl)) return FALSE;
gint ptr;
for(ptr=0; ptr<strlen(buf); ptr++) if(buf[ptr]=='=') break;
if(ptr>=strlen(buf)) return FALSE;
gint dptr=0;
ptr++;
while(buf[ptr]!=' ' && buf[ptr]!='\0') buf[dptr++]=buf[ptr++];
buf[dptr++]='\0';
return TRUE;
}
gint get_line_parameter_int(gchar *buf, const gchar *tpl){//поиск строки по шаблону и возврат целочисленного значения после символа '='
if(!get_line_parameter_string(buf, tpl)) return FALSE;
gint ptr, dig;
gint res=0, len=strlen(buf);
for(ptr=0;ptr<len;ptr++){
dig=buf[ptr]-'0';
if(dig>9) return 0;
res=res*10+dig;
}
return res;
}
gboolean check_line_on_comment(const gchar *tpl){ //поиск строки по шаблону и проверка на закомментированность
gint ptr=f_str_s(tpl); //возвращает FALSE если строки нет или она закоментирована
if(!ptr) return FALSE;
while(grc.file_buf[ptr]!='\0' || grc.file_buf[ptr]!='\n'){
if(grc.file_buf[ptr]==' ') {ptr++; continue;}
if(grc.file_buf[ptr++]=='#') return FALSE;
else break;
}
return TRUE;
}
void StringRoutine(){ // Обработка файла-конфига
gchar buf[200];
if(grc.savedefault){
sprintf(buf,"%s%s\n",tmpl1,"=saved"); //создаю новую строку
facs(tmpl1, buf);
sprintf(buf,"%s\n", tmpl2); //добавляю,
if(!facs(tmpl2, buf)) // если требуется, GRUB_SAVEDEFAULT=true
add_str_aft_line(tmpl1, buf);
}
else {
sprintf(buf,"%s%s\n",tmpl1,"=0"); //устанавливаю первоначальное значение
facs(tmpl1, buf);
facs(tmpl2, "");
}
sprintf(buf,"%s=%i\n", tmpl3, grc.timeout); //задаю таймаут
facs(tmpl3, buf);
*buf='\0';
if(grc.recovery) strcpy (buf,"#"); //определяюсь с пунктами recovery mode
if(f_str(tmpl4)){ //поиск и замена ведется по двум шаблонам
strcat(buf, tmpl4); strcat(buf,"=true\n");// GRUB_DISABLE_LINUX_RECOVERY и GRUB_DISABLE_RECOVERY
facs(tmpl4, buf); //потому-шта в разных версиях груба они различаюца
}
else {
strcat(buf, tmpl4_1); strcat(buf,"=true\n");
facs(tmpl4_1, buf);
}
sprintf(buf,"%s=\"%s\"\n", tmpl7, default_melody);//настраиваю бип
if(grc.playsound){
if(!facs(tmpl7, buf)){
strcat(grc.file_buf, "\n");
strcat(grc.file_buf, buf);
}
}
else facs(tmpl7, "");
if(grc.wallpaper){ //обновляю разрешение экрана
sprintf(buf,"%s=%ix%i\n", tmpl5, grc.x_res, grc.y_res);
facs (tmpl5, buf);
sprintf(buf,"%s=%s\n", tmpl6, boot_img);
if(!facs(tmpl6,buf)){
strcat(grc.file_buf,"\n");
strcat(grc.file_buf,buf); //добавляю в конец GRUB_BACKGROUND=path
}
}
else {
sprintf(buf,"#%s=640x480\n", tmpl5);
facs (tmpl5, buf);
facs(tmpl6,"");
}
int i=strlen(grc.file_buf); //удаляю лишние пробелы и перевод строки в конце буфера
if(grc.file_buf[i-1]){
i--;
while(grc.file_buf[i]=='\n' || grc.file_buf[i]==' ') i--;
grc.file_buf[++i]='\0';
}
grc.lfSize=i*sizeof(gchar);
g_print("\n\nСодержимое конфига:\n%s\n\n", grc.file_buf);
}
void MemtestMove(){ //перенос файла memtest86+
// ПОКА ЭТО ПУСТЫШКА. НА ДНЯХ ДОБАВЛЮ
}
static void ApplySettings(){
const gchar *errprefw="can't writting to file:";
const gchar *errprefo="missing opening file:";
if( !InputControl()){
MessageBox("Error input screen resolution");
return;
}
/* Контрольно считываю параметры */
grc.timeout = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_button));
grc.wallpaper = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chkbx[0]));
grc.savedefault = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chkbx[1]));
grc.recovery = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chkbx[2]));
grc.memtest = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chkbx[3]));
grc.playsound = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chkbx[4]));
if(grc.filepath) grc.wallpaper=TRUE;
else grc.wallpaper=FALSE;
g_free(grc.file_buf);
grc.file_buf=FileToBuffers(def_grub);
if (!grc.file_buf) MessError(errprefo, def_grub);
gint rnd=87687, len=100; // Буфера и в них имена временных файлов
gchar *t_img=g_malloc(len);
gchar *t_wrk=g_malloc(len);
gchar *t_fsc=g_malloc(len);
grc.work_file_buf=g_malloc(grc.lfSize*2); // Выделяю память для рабочих буферов
memcpy(grc.work_file_buf, grc.file_buf, grc.lfSize);
g_free(grc.file_buf);
grc.file_buf=g_malloc(grc.lfSize*2); // Буфер для нового содержимого конфига
memcpy(grc.file_buf, grc.work_file_buf, grc.lfSize);
grc.file_buf[grc.lfSize]=grc.work_file_buf[grc.lfSize]='\0';
sprintf(t_wrk, "/tmp/wrk_tmp_%i.tmp",rnd);// Имена временных файлов
sprintf(t_fsc, "/tmp/fsc_tmp_%i.sh",rnd);
StringRoutine(); // Обработка файла-конфига
if(grc.wallpaper) ImageConvert(); // Обработка изображения
MemtestMove();
long lWrite;
FILE *pFile=fopen(t_wrk, "wb"); // Сбрасываю буфер с новым содержимым во временный файл
if (pFile) lWrite=fwrite (grc.file_buf , 1 , grc.lfSize, pFile );
if(pFile && lWrite==grc.lfSize){
fclose (pFile); pFile=NULL;
gchar *t_scr=malloc(200*sizeof(gchar)); // Создаю скрипт, чтобы не вызывать gksu по несколько раз
if(grc.wallpaper) // Если надо скопировать картинку
sprintf(t_scr,"#!/bin/sh\nmv %s %s\ncp %s %s_save\nmv %s %s\nchown root:root %s\nupdate-grub",
grc.t_image_name, boot_img, def_grub, def_grub, t_wrk, def_grub, def_grub);
else sprintf(t_scr,"#!/bin/sh\ncp %s %s_save\nmv %s %s\nchown root:root %s\nupdate-grub",
def_grub, def_grub, t_wrk, def_grub, def_grub);
g_print("\n\nТекст скрипта:\n%s\n\n", t_scr);
gboolean fl=FALSE;
glong sSize=strlen(t_scr)*sizeof(gchar), sWrite=0;
FILE *sFile=fopen(t_fsc, "wb"); // Создаю файл со скриптом
if (sFile) sWrite=fwrite (t_scr , 1, sSize , sFile );
if (!sFile || sSize!=sWrite) MessError(errprefw, t_fsc);
else {
fclose (sFile); sFile=NULL; fl=TRUE;
sprintf(t_img,"chmod +x %s", t_fsc);
system(t_img);
sprintf(t_img,"gksu %s", t_fsc); // Создаю команду запуска скрипта
system(t_img); // Выполняю эту команду
}
if (sFile) fclose (sFile);
if (fl) remove (t_fsc); // Удаляю файл со скриптом
g_free(t_scr); // Освобождаю буфер скрипта
}
else {
MessError(errprefw, t_wrk);
fclose (pFile);
}
g_free(t_img); g_free(t_wrk); g_free(t_fsc);// Возвращаю память куче
}
void UpdatePath(){
if( ! grc.filepath ) return;
if(!filepath) filepath=g_malloc((size_t)file_path_len);
strcpy(filepath, grc.filepath);
int i, len=strlen(grc.filepath);
for(i=len; i>0; i--) if (filepath[i]=='/') {
filepath[i]='\0'; break;
}
}
gboolean LoadImagePrewiev(){
// GError *error;
PixBuffer=gdk_pixbuf_new_from_file_at_size(grc.filepath, thumb_width, thumb_height, NULL);// &error);
gtk_image_set_from_pixbuf(GTK_IMAGE(thumb), PixBuffer);
return TRUE;
}
gboolean ShowURL(GtkAboutDialog *about, const gchar *url, gpointer data){
gtk_show_uri(NULL, url, 0, NULL);
return TRUE;
}
void AboutDialog(GtkWidget * widget, gpointer data){
const gchar* autor_a[]={
"Terechov Wladislav\n Conquistador ™\n e-mail: asgrem@gmail.com\nhttp://my.mail.ru/community/win_xp/",
NULL};
const gchar* name_a="About";
const gchar* prog_a="Grub Configurator";
const gchar* vers_a="0.1";
const gchar* copy_a="free software";
// const gchar* site_a="http://my.mail.ru/community/win_xp/";
const gchar* coms_a="Configurator of GRand Unified Bootloader";
GtkAboutDialog *dialog=GTK_ABOUT_DIALOG(gtk_about_dialog_new());
GdkPixbuf *pict=gdk_pixbuf_new_from_file(logo_path, NULL);
gtk_about_dialog_set_name(dialog, name_a);
gtk_about_dialog_set_program_name(dialog, prog_a);
gtk_about_dialog_set_version(dialog, vers_a);
gtk_about_dialog_set_copyright(dialog, copy_a);
gtk_about_dialog_set_comments(dialog, coms_a);
gtk_about_dialog_set_authors(dialog, autor_a);
gtk_about_dialog_set_logo(dialog, pict);
g_signal_connect(G_OBJECT(dialog), "activate-link", G_CALLBACK(ShowURL), NULL);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET(dialog));
}
GtkWidget *LabelSet(const gchar *string){
GtkWidget *label=gtk_label_new(string);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD); //PANGO_WRAP_CHAR, PANGO_WRAP_WORD_CHAR
return label;
}
static void AttentionMessage(GtkWidget * widget, gpointer data){
MessageBox(STRING_1);
}
static void PriviewImage(GtkWidget * widget, gpointer data){
if(!grc.filepath) return;
ImageConvert();
GtkWidget *image = gtk_image_new();
GdkPixbuf *pb=gdk_pixbuf_new_from_file_at_size(grc.t_image_name, grc.x_preview, grc.y_preview, NULL);// &error);
gtk_image_set_from_pixbuf(GTK_IMAGE(image), pb);
GtkWidget *dialog=gtk_dialog_new_with_buttons ("Preview", main_window,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
GtkWidget *box=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
gtk_box_pack_start(GTK_BOX(box), image, TRUE, TRUE, 0);
gtk_widget_show(image);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy (GTK_WIDGET(dialog));
}
static gboolean delete_event(GtkWidget * widget, GdkEvent * event, gpointer data){
g_print("Delete event occurred\n");
return FALSE;
}
static void destroy(GtkWidget * widget, gpointer data){
gtk_main_quit();
}
static void toogle_callback(GtkWidget *togglebutton, gboolean *data){ //обработка сигналов от чек-батонов
*data=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton));
gchar *labl = *data ? "Enable" : "Disable";
gtk_button_set_label(GTK_BUTTON(togglebutton), labl);
if( togglebutton == chkbx[0] ){ //при изменении состояния кнопки обоев...
if(*data){
grc.filepath=save_filepath;
UpdatePath();
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (file_button), filepath);
if(grc.filepath) LoadImagePrewiev();
gtk_entry_set_editable(GTK_ENTRY(resolution), TRUE);
}
else {
if(!filepath) {
filepath=g_malloc((size_t)file_path_len);
}
strcpy(filepath, DefaultImagePath);
grc.filepath=NULL;
gtk_image_set_from_pixbuf(GTK_IMAGE(thumb), PixBuffer_logo);
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (file_button), filepath);
gtk_entry_set_editable(GTK_ENTRY(resolution), FALSE);
}
}
}
void set_toggle_button_state(GtkWidget *button, gboolean *flag) { // Установка начального состояния тоггл-кнопок
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), *flag);
toogle_callback(button, flag);
}
void file_selected_event(GtkFileChooserButton *fc_button, gpointer user_data) {
if(grc.filepath)g_free(grc.filepath);
save_filepath=grc.filepath=gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fc_button));
grc.wallpaper=TRUE; //устанавливаю кнопку обоев в "enable"
set_toggle_button_state(chkbx[0],&grc.wallpaper);
}
void update_parameter(){ //обновление параметров согласно файлу-конфигу grub
gchar *buf=g_malloc(256);
get_line_parameter_string(buf, tmpl1);
if(strcmp(buf,"saved") || f_str(tmpl2))grc.savedefault=TRUE;
grc.timeout=get_line_parameter_int(buf, tmpl3);
if(!check_line_on_comment(tmpl4) && !check_line_on_comment(tmpl4_1)) grc.recovery=TRUE;
gboolean res1=check_line_on_comment(tmpl4);
gboolean res2=check_line_on_comment(tmpl4_1);
g_print("%s - %i\n%s - %i", tmpl4, (int)res1, tmpl4_1, (int)res2);
if(f_str(tmpl6)){
grc.wallpaper=TRUE;
if(get_line_parameter_string(buf,tmpl6)){
save_filepath=grc.filepath=g_malloc(file_path_len);
strcpy(grc.filepath, buf);
}}
if(f_str(tmpl7)) grc.playsound=TRUE;
g_free(buf);
}
int main(int argc, char ** argv){
GtkWidget * window;
GtkWidget * box;
gint i;
gtk_init(&argc, &argv);
ScreenResolution=g_malloc(20); // Выделяю буфер для строчки с разрешением
/* Определяю разрешение экрана и превью */
int nsizes;
Display *dpy = XOpenDisplay(NULL);
XRRScreenSize *ss = XRRSizes(dpy, 0, &nsizes);
grc.x_res=ss->width; grc.y_res=ss->height;
XCloseDisplay(dpy);
grc.x_preview = grc.x_res/3*2;
grc.y_preview = grc.y_res/3*2;
const gchar *temp_image_name="/tmp/img_tmp_file.jpg";// Имя временного файла-изображения
grc.t_image_name=g_malloc((strlen(temp_image_name)+1)*sizeof(gchar));
strcpy(grc.t_image_name, temp_image_name);
GtkFilter = gtk_file_filter_new (); // Инициализация файловых фильтров
gtk_file_filter_set_name(GtkFilter, "Images");
for(i=0; i<FilterCount; i++) gtk_file_filter_add_pattern (GtkFilter, FileFilters[i]);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
main_window = GTK_WINDOW(window); // Сохраняю идентификатор главного окна глобально для диалогов
gtk_window_set_default_size (GTK_WINDOW (window), win_width, win_height);
gtk_window_set_title(GTK_WINDOW(window), "Grub Configurator");
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
box=gtk_table_new(10, 2, FALSE);
gtk_container_add(GTK_CONTAINER(window), box);
grc.file_buf=FileToBuffers(def_grub);
grc.timeout = default_timeout;
grc.wallpaper=grc.savedefault=grc.recovery=grc.memtest=grc.playsound=FALSE;
update_parameter();
/* лебел - выбор изображения 1 строчка */
lebel[0]=LabelSet("Background image:");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[0], 0, 1, 0, 1);
gtk_widget_show(lebel[0]);
// чекбокс background
chkbx[0]=gtk_toggle_button_new();
gtk_table_attach_defaults(GTK_TABLE(box), chkbx[0], 1, 2, 0, 1);
g_signal_connect(G_OBJECT(chkbx[0]), "toggled", G_CALLBACK(toogle_callback), &grc.wallpaper);
gtk_widget_show(chkbx[0]);
/* иконка предпросмотра и кнопка выбора файла 2 строчка */
thumb = gtk_image_new();
PixBuffer_logo=PixBuffer=gdk_pixbuf_new_from_file_at_size(logo_path, thumb_width, thumb_height, NULL);// &error);
if(grc.filepath) LoadImagePrewiev();
else gtk_image_set_from_pixbuf(GTK_IMAGE(thumb), PixBuffer);
button[3]=gtk_button_new();
gtk_button_set_relief(GTK_BUTTON(button[3]), GTK_RELIEF_NONE);
gtk_button_set_focus_on_click(GTK_BUTTON(button[3]), FALSE);
gtk_button_set_image(GTK_BUTTON(button[3]), thumb);
g_signal_connect(G_OBJECT(button[3]), "clicked", G_CALLBACK(PriviewImage), window);
gtk_table_attach_defaults(GTK_TABLE(box), button[3], 0, 1, 1, 2);
gtk_widget_show(button[3]);
file_button=gtk_file_chooser_button_new("Select Image File", GTK_FILE_CHOOSER_ACTION_OPEN); //GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (file_button), DefaultImagePath);
gtk_file_chooser_button_set_width_chars(GTK_FILE_CHOOSER_BUTTON (file_button), 15);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (file_button), GtkFilter);
g_signal_connect(G_OBJECT(file_button), "file-set", G_CALLBACK(file_selected_event), NULL);
gtk_table_attach_defaults(GTK_TABLE(box), file_button, 1, 2, 1, 2);
gtk_widget_show(file_button);
/* выбор разрешения 3 строчка */
lebel[1]=LabelSet("Input default screen resolution:");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[1], 0, 1, 2, 3);
gtk_widget_show(lebel[1]);
gchar res[20];
sprintf(res,"%ix%i", grc.x_res, grc.y_res);
TextBufferRes=gtk_entry_buffer_new(res, strlen(res));
resolution=gtk_entry_new_with_buffer(TextBufferRes);
gtk_entry_set_max_length(GTK_ENTRY(resolution), 9);
gtk_entry_set_editable(GTK_ENTRY(resolution), FALSE);
gtk_table_attach_defaults(GTK_TABLE(box), resolution, 1, 2, 2, 3);
gtk_widget_show(resolution);
/* спин timeout 4 строчка */
lebel[2]=LabelSet("Grub timeout:");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[2], 0, 1, 3, 4);
gtk_widget_show(lebel[2]);
spin_button=gtk_spin_button_new_with_range(0,120,1); // Добавляю спинер
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_button), grc.timeout);
gtk_table_attach_defaults(GTK_TABLE(box), spin_button, 1, 2, 3, 4);
gtk_widget_show(spin_button);
/* чекбокс savedefault 5 строчка */
lebel[3]=LabelSet("Save last item as default:");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[3], 0, 1, 4, 5);
gtk_widget_show(lebel[3]);
chkbx[1]=gtk_toggle_button_new_with_label ("Disable");
gtk_table_attach_defaults(GTK_TABLE(box), chkbx[1], 1, 2, 4, 5);
g_signal_connect(G_OBJECT(chkbx[1]), "toggled", G_CALLBACK(toogle_callback), &grc.savedefault);
gtk_widget_show(chkbx[1]);
/* чекбокс recovery mode 6 строчка */
lebel[4]=LabelSet("Items \"Recovery mode\":");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[4], 0, 1, 5, 6);
gtk_widget_show(lebel[4]);
chkbx[2]=gtk_toggle_button_new_with_label ("Disable");
gtk_table_attach_defaults(GTK_TABLE(box), chkbx[2], 1, 2, 5, 6);
g_signal_connect(G_OBJECT(chkbx[2]), "toggled", G_CALLBACK(toogle_callback), &grc.recovery);
gtk_widget_show(chkbx[2]);
/* чекбокс memtest86+ 7 строчка */
lebel[5]=LabelSet("Items \"memtest86+\":");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[5], 0, 1, 7, 8);
gtk_widget_show(lebel[5]);
chkbx[3]=gtk_toggle_button_new_with_label ("Disable");
gtk_table_attach_defaults(GTK_TABLE(box), chkbx[3], 1, 2, 7, 8);
g_signal_connect(G_OBJECT(chkbx[3]), "toggled", G_CALLBACK(toogle_callback), &grc.memtest);
gtk_widget_show(chkbx[3]);
/* чекбокс playsound 8 строчка */
lebel[6]=LabelSet("Play sound on start:");
gtk_table_attach_defaults(GTK_TABLE(box), lebel[6], 0, 1, 8, 9);
gtk_widget_show(lebel[6]);
chkbx[4]=gtk_toggle_button_new_with_label ("Disable");
gtk_table_attach_defaults(GTK_TABLE(box), chkbx[4], 1, 2, 8, 9);
g_signal_connect(G_OBJECT(chkbx[4]), "toggled", G_CALLBACK(toogle_callback), &grc.playsound);
gtk_widget_show(chkbx[4]);
/* кнопка Read My 9 строчка */
button[0]=gtk_button_new_with_label("Read my!");
gtk_table_attach_defaults(GTK_TABLE(box), button[0], 0, 2, 9, 10);
g_signal_connect(G_OBJECT(button[0]), "clicked", G_CALLBACK(AttentionMessage), &button[0]);
gtk_widget_show(button[0]);
gtk_container_set_focus_child(GTK_CONTAINER(box), button[0]); //устанавливаю фокус на кнопку ReadMy
/* кнопка About 10 строчка */
button[1]=gtk_button_new_with_label("About");
gtk_table_attach_defaults(GTK_TABLE(box), button[1], 0, 1, 10, 11);
g_signal_connect(G_OBJECT(button[1]), "clicked", G_CALLBACK(AboutDialog), &button[1]);
gtk_widget_show(button[1]);
// кнопка Apply
button[2]=gtk_button_new_with_label("Apply settings!");
gtk_table_attach_defaults(GTK_TABLE(box), button[2], 1, 2, 10, 11);
g_signal_connect(G_OBJECT(button[2]), "clicked", G_CALLBACK(ApplySettings), &button[1]);
gtk_widget_show(button[2]);
set_toggle_button_state(chkbx[0], &grc.wallpaper); //"нажимаю" кнопки согласно конфига
set_toggle_button_state(chkbx[1], &grc.savedefault);
set_toggle_button_state(chkbx[2], &grc.recovery);
set_toggle_button_state(chkbx[3], &grc.memtest);
set_toggle_button_state(chkbx[4], &grc.playsound);
gtk_widget_show(box);
gtk_widget_show(window);
gtk_main();
g_free(grc.t_image_name);
if(ScreenResolution) g_free(ScreenResolution);
if(grc.filepath) g_free(grc.filepath);
if(filepath) g_free(filepath);
if(save_filepath!=grc.filepath && save_filepath) g_free(save_filepath);
return 0;
}