"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "zfuncs.cc" between
fotoxx-22.30.tar.gz and fotoxx-22.35.tar.gz

About: fotoxx is a program for photo editing and collection management.

zfuncs.cc  (fotoxx-22.30):zfuncs.cc  (fotoxx-22.35)
skipping to change at line 183 skipping to change at line 183
showz_html show a local or remote HTML file showz_html show a local or remote HTML file
showz_docfile show a document file topic and associated image showz_docfile show a document file topic and associated image
audit_docfile audit docfile for missing topics and bad links audit_docfile audit docfile for missing topics and bad links
GTK Utility Functions GTK Utility Functions
--------------------- ---------------------
zmainloop do main loop to process menu events, etc. zmainloop do main loop to process menu events, etc.
zmainsleep loop zmainloop and zsleep for designated time zmainsleep loop zmainloop and zsleep for designated time
draw_context_create get cairo drawing context for GDK window draw_context_create get cairo drawing context for GDK window
textwidget text report, navigation, line editing textwidget text report, navigation, line editing
menus / toolbars simplified GTK menus, toolbars and status bars create_menubar menubar functions
create_toolbar toolbar functions
create_stbar statusbar functions
create_popmenu implement popup menus create_popmenu implement popup menus
Vmenu vertical menu/toolbar in vertical packing box Vmenu vertical menu/toolbar in vertical packing box
splcurve_init set up a spline curve drawing area splcurve_init set up a spline curve drawing area
splcurve_adjust mouse event function to manipulate curve nodes splcurve_adjust mouse event function to manipulate curve nodes
splcurve_addnode add an anchor point to a curve splcurve_addnode add an anchor point to a curve
splcurve_resize resize drawing area if too small splcurve_resize resize drawing area if too small
splcurve_draw draw curve through nodes splcurve_draw draw curve through nodes
splcurve_generate generate x/y table of values from curve splcurve_generate generate x/y table of values from curve
splcurve_yval get curve y-value for given x-value splcurve_yval get curve y-value for given x-value
skipping to change at line 253 skipping to change at line 255
zdialog_geometry load/save zdialog positions at app start/exit zdialog_geometry load/save zdialog positions at app start/exit
zdialog_set_position set zdialog position: null mouse desktop parent sa ve nn/nn zdialog_set_position set zdialog position: null mouse desktop parent sa ve nn/nn
zdialog_save_position remember zdialog position relative to parent zdialog_save_position remember zdialog position relative to parent
zdialog_save_inputs save zdialog inputs when zdialog completed zdialog_save_inputs save zdialog inputs when zdialog completed
zdialog_restore_inputs retrieve prior zdialog input fields zdialog_restore_inputs retrieve prior zdialog input fields
zdialog_text popup zdialog to get N lines of text input from us er zdialog_text popup zdialog to get N lines of text input from us er
zdialog_text1 popup zdialog to get one line of text input from u ser zdialog_text1 popup zdialog to get one line of text input from u ser
zdialog_choose popup zdialog to show a message, select a button, return choice zdialog_choose popup zdialog to show a message, select a button, return choice
zdialog_choose2 popup zdialog, same as above with addition of KB i nputs zdialog_choose2 popup zdialog, same as above with addition of KB i nputs
zdialog_picklist popup zdialog with pick list, returns choice
zdialog_popup_text get chars/text for GtkTextView widget insert 22.15 zdialog_popup_text get chars/text for GtkTextView widget insert 22.15
popup_report popup window and scrolling text report popup_report popup window and scrolling text report
popup_command run a shell command with output in a popup window popup_command run a shell command with output in a popup window
zmessageACK popup message, printf format, wait for user ACK zmessageACK popup message, printf format, wait for user ACK
zmessageYN popup message, printf format, wait for user Yes / No zmessageYN popup message, printf format, wait for user Yes / No
zmessage_post popup message, printf format, show until killed zmessage_post popup message, printf format, show until killed
zmessage_post_bold popup message, printf format, big bold red font zmessage_post_bold popup message, printf format, big bold red font
poptext_screen popup message at given absolute screen position poptext_screen popup message at given absolute screen position
poptext_mouse popup message at current mouse position + offset poptext_mouse popup message at current mouse position + offset
poptext_window popup message at given window position + offset poptext_window popup message at given window position + offset
poptext_widget popup message at given widget position + offset poptext_widget popup message at given widget position + offset
poptext_killnow kill popup message poptext_killnow kill popup message
popup_image show an image in a small popup window popup_image show an image in a small popup window
popup_picklist popup picklist, return choice
zgetfile simplified file chooser zdialog zgetfile simplified file chooser zdialog
zgetfolder file chooser for folder, with create option zgetfolder file chooser for folder, with create option
print_image_file zdialog to print an image file using GTK functions print_image_file zdialog to print an image file using GTK functions
drag_drop_source connect window as drag-drop source drag_drop_source connect window as drag-drop source
drag_drop_dest connect window as drag-drop destination drag_drop_dest connect window as drag-drop destination
get_thumbnail get thumbnail image for given image file get_thumbnail get thumbnail image for given image file
zmakecursor make a cursor from an image file (.png .jpg) zmakecursor make a cursor from an image file (.png .jpg)
gdk_pixbuf_rotate rotate a pixbuf through any angle gdk_pixbuf_rotate rotate a pixbuf through any angle
gdk_pixbuf_stripalpha remove an alpha channel from a pixbuf gdk_pixbuf_stripalpha remove an alpha channel from a pixbuf
text_pixbuf create pixbuf containing text text_pixbuf create pixbuf containing text
skipping to change at line 640 skipping to change at line 642
strcpy(zstring,string); strcpy(zstring,string);
return cc; return cc;
} }
/******************************************************************************* */ /******************************************************************************* */
// add message to stdout log file if Floglevel >= message level // add message to stdout log file if Floglevel >= message level
// flush every output immediately even if stdout is a file // flush every output immediately even if stdout is a file
// use lev = 0 for mandatory error message // use lev = 0 for mandatory error message
// lev = 1 for informative message // lev = 1 for informative message
// lev = 2 for dialog inputs // lev = 2 for everything
void Plog(int lev, cchar *format, ...) void Plog(int lev, cchar *format, ...)
{ {
if (lev > Floglevel) return; if (lev > Floglevel) return;
va_list arglist; va_list arglist;
va_start(arglist,format); va_start(arglist,format);
vprintf(format,arglist); vprintf(format,arglist);
va_end(arglist); va_end(arglist);
fflush(stdout); fflush(stdout);
skipping to change at line 663 skipping to change at line 665
/******************************************************************************* */ /******************************************************************************* */
// output a popup message not requiring GTK // output a popup message not requiring GTK
void xmessage(cchar *message) void xmessage(cchar *message)
{ {
char command[200]; char command[200];
cchar *font = "-*-*-*-*-*--*-200-*-*-*-*-*-*"; // big font cchar *font = "-*-*-*-*-*--*-200-*-*-*-*-*-*"; // big font
Plog(1,"%s\n",message); Plog(0,"%s\n",message);
snprintf(command,200,"xmessage -font \'%s\' -center \" %s \" ",font,message); snprintf(command,200,"xmessage -font \'%s\' -center \" %s \" ",font,message);
int err = system(command); // do not use zshell int err = system(command); // do not use zshell
if (err || 1) return; if (err) return;
// avoid gcc warning
return;
} }
/******************************************************************************* */ /******************************************************************************* */
// Output a status or error message and kill all processes in the process group . // Output a status or error message and kill all processes in the process group .
// killpg(0,SIGKILL) kills all processes, including the caller. // killpg(0,SIGKILL) kills all processes, including the caller.
void zexit(cchar *errmess, ...) void zexit(cchar *errmess, ...)
{ {
va_list arglist; va_list arglist;
skipping to change at line 776 skipping to change at line 779
"*** if possible, please explain how to repeat this problem *** \n"); "*** if possible, please explain how to repeat this problem *** \n");
cc = readlink("/proc/self/exe",progexe,300); // get own program path cc = readlink("/proc/self/exe",progexe,300); // get own program path
if (cc > 0) progexe[cc] = 0; // readlink() quirk if (cc > 0) progexe[cc] = 0; // readlink() quirk
else { else {
fprintf(fid2,"progexe not available \n"); fprintf(fid2,"progexe not available \n");
Flinenos = 0; Flinenos = 0;
} }
err = zshell(0,"which addr2line >> /dev/null"); // check if addr2line() available err = zshell(0,"which addr2line >> /dev/null"); // check if addr2line() available
if (err) { if (err) Flinenos = 0;
fprintf(fid2,"addr2line not available \n");
Flinenos = 0;
}
for (ii = 0; ii < nstack; ii++) // loop backtrace records for (ii = 0; ii < nstack; ii++) // loop backtrace records
{ {
pp1 = pp2 = 0; pp1 = pp2 = 0;
fgets_trim(buff1,300,fid1); // read backtrace line fgets_trim(buff1,300,fid1); // read backtrace line
if (! Flinenos) goto output; if (! Flinenos) goto output;
pfunc = 0; pfunc = 0;
pp1 = strstr(buff1,"+0x"); // new format (+0x12345...) pp1 = strstr(buff1,"+0x"); // new format (+0x12345...)
if (pp1) pp2 = strchr(pp1,')'); if (pp1) pp2 = strchr(pp1,')');
else { else {
skipping to change at line 981 skipping to change at line 981
// return: 0 OK // return: 0 OK
// 1 password not entered // 1 password not entered
// N other error // N other error
// this fails for appimage executables, for unknown reasons // this fails for appimage executables, for unknown reasons
int runroot(cchar *command) // 22.1 int runroot(cchar *command) // 22.1
{ {
int err; int err;
char *pw, command2[500]; char *pw, command2[500];
Plog(1,"runroot: %s \n",command); Plog(0,"runroot: %s \n",command);
pw = zdialog_text1(0,"root password",0); // get password from user pw = zdialog_text1(0,"root password",0); // get password from user
if (! pw || ! pw[0]) { if (! pw || ! pw[0]) {
zmessageACK(0,"nothing done"); zmessageACK(0,"nothing done");
return 1; return 1;
} }
snprintf(command2,500,"echo %s | sudo -S %s &\n",pw,command); // sudo with password and user command snprintf(command2,500,"echo %s | sudo -S %s &\n",pw,command); // sudo with password and user command
err = zshell("ack",command2); // run command (and wait for completion) err = zshell("ack",command2); // run command (and wait for completion)
skipping to change at line 1735 skipping to change at line 1735
if (ftf) { // first call if (ftf) { // first call
ftf = 0; ftf = 0;
Nsmp = get_nprocs(); // get SMP CPU count Nsmp = get_nprocs(); // get SMP CPU count
} }
if (cpu >= Nsmp) return; if (cpu >= Nsmp) return;
CPU_ZERO(&cpuset); CPU_ZERO(&cpuset);
CPU_SET(cpu,&cpuset); CPU_SET(cpu,&cpuset);
err = sched_setaffinity(0,sizeof(cpuset),&cpuset); err = sched_setaffinity(0,sizeof(cpuset),&cpuset);
if (err) Plog(1,"set_cpu_affinity() %s \n",strerror(errno)); if (err) Plog(2,"set_cpu_affinity() %s \n",strerror(errno));
return; return;
} }
/******************************************************************************* * /******************************************************************************* *
int err = zshell(cchar *options, cchar *command, ...) int err = zshell(cchar *options, cchar *command, ...)
Format and perform a shell command, wait for completion, return status. Format and perform a shell command, wait for completion, return status.
Suitable for commands that do not stop the GTK main loop > 2 seconds. Suitable for commands that do not stop the GTK main loop > 2 seconds.
skipping to change at line 1759 skipping to change at line 1759
command: shell command with optional '%' printf formats command: shell command with optional '%' printf formats
... : optional arguments to stuff into printf formats ... : optional arguments to stuff into printf formats
returns: status of the shell command returns: status of the shell command
***/ ***/
int zshell(cchar *options, cchar *command, ...) int zshell(cchar *options, cchar *command, ...)
{ {
void * zshell_thread(void *);
int Flog, Fack; int Flog, Fack;
va_list arglist; va_list arglist;
int err, cc, ccmax = 2*XFCC; int err, cc, ccmax = 2*XFCC;
char command2[2*XFCC]; char command2[2*XFCC];
Flog = Fack = 0; Flog = Fack = 0;
if (options) { if (options) {
if (strstr(options,"log")) Flog = 1; // set options if (strstr(options,"log")) Flog = 1; // set options
if (strstr(options,"ack")) Fack = 1; if (strstr(options,"ack")) Fack = 1;
skipping to change at line 1783 skipping to change at line 1781
va_start(arglist,command); // format command va_start(arglist,command); // format command
cc = vsnprintf(command2,ccmax,command,arglist); cc = vsnprintf(command2,ccmax,command,arglist);
va_end(arglist); va_end(arglist);
if (cc >= ccmax) zappcrash("zshell: buffer overflow: %d",cc); if (cc >= ccmax) zappcrash("zshell: buffer overflow: %d",cc);
if (Flog) Plog(0,"zshell: %s \n",command2); // command > log file if wanted if (Flog) Plog(0,"zshell: %s \n",command2); // command > log file if wanted
err = system(command2); // run command, returns when done err = system(command2); // run command, returns when done
err = WEXITSTATUS(err); // get command status err = WEXITSTATUS(err); // get command status
if (err > 1) { if (err) {
// suppress operation not permitted if (! Flog) Plog(0,"zshell: %s \n",command2);
// log command if not already 22.31
Plog(0,"zshell error: %s \n",strerror(err)); // log error Plog(0,"zshell error: %s \n",strerror(err)); // log error
if (Fack) zmessageACK(mainwin,strerror(err)); if (Fack) zmessageACK(mainwin,"command: %s \n error: %s",
// popup error to user if wanted command2, strerror(err));
// popup error to user if wanted
} }
return err; // return completion status return err; // return completion status
} }
/******************************************************************************* * /******************************************************************************* *
int err = zshell_gtk(cchar *options, cchar *command, ...) int err = zshell_gtk(cchar *options, cchar *command, ...)
Format and perform a shell command, wait for completion, return status. Format and perform a shell command, wait for completion, return status.
skipping to change at line 2186 skipping to change at line 2186
strcpy(pp2,pp1); strcpy(pp2,pp1);
dfile = dfile2; // output file full path dfile = dfile2; // output file full path
} }
else { // output is a file path else { // output is a file path
pp2 = (char *) dfile; pp2 = (char *) dfile;
pp2 = strrchr(pp2+1,'/'); pp2 = strrchr(pp2+1,'/');
if (pp2) *pp2 = 0; if (pp2) *pp2 = 0;
err = zshell("ack","mkdir -p -m 0750 \"%s\" ",dfile); err = zshell("ack","mkdir -p -m 0750 \"%s\" ",dfile);
if (pp2) *pp2 = '/'; if (pp2) *pp2 = '/';
if (err) { if (err) return errno;
Plog(0,"%s \n %s \n",strerror(errno),dfile);
return errno;
}
} }
err = lstat(sfile,&statB); // get input file attributes err = lstat(sfile,&statB); // get input file attributes
if (err) { if (err) {
Plog(0,"%s \n %s \n",strerror(errno),sfile); Plog(0,"%s \n %s \n",strerror(errno),sfile);
return errno; return errno;
} }
if (S_ISLNK(statB.st_mode)) { // input file is symlink if (S_ISLNK(statB.st_mode)) { // input file is symlink
cc = readlink(sfile,buff,XFCC); cc = readlink(sfile,buff,XFCC);
skipping to change at line 2263 skipping to change at line 2260
/******************************************************************************* */ /******************************************************************************* */
// copy a file using shell 'cp' command // copy a file using shell 'cp' command
// file owner, permissions, and timestamps are copied // file owner, permissions, and timestamps are copied
// returns 0 if OK, else errno // returns 0 if OK, else errno
int cp_copy(cchar *sfile, cchar *dfile) int cp_copy(cchar *sfile, cchar *dfile)
{ {
if (strmatch(sfile,dfile)) { if (strmatch(sfile,dfile)) {
Plog(1,"ignore copy file to self: %s \n",sfile); Plog(0,"ignore copy file to self: %s \n",sfile);
return 0; return 0;
} }
int err = zshell(0,"cp -f -p \"%s\" \"%s\" ",sfile,dfile); int err = zshell(0,"cp -f -p \"%s\" \"%s\" ",sfile,dfile);
return err; return err;
} }
/******************************************************************************* */ /******************************************************************************* */
// get the available space on disk of the given file // get the available space on disk of the given file
skipping to change at line 3815 skipping to change at line 3812
return output[ii]; return output[ii];
} }
/******************************************************************************* * /******************************************************************************* *
Wildcard string match Wildcard string match
Match candidate string to wildcard string containing any number of Match candidate string to wildcard string containing any number of
'*' or '?' wildcard characters. '*' matches any number of characters, '*' or '?' wildcard characters. '*' matches any number of characters,
including zero characters. '?' matches any one character. including zero characters. '?' matches any one character.
Returns 0 if match, 1 if no match. Returns 0 if match, 1 if no match. <<---- WATCH OUT !
Benchmark: 0.032 usec. wild = *asdf*qwer?yxc Benchmark: 0.032 usec. wild = *asdf*qwer?yxc
3.3 GHz Core i5 match = XXXasdfXXXXqwerXyxc 3.3 GHz Core i5 match = XXXasdfXXXXqwerXyxc
******************************************************************************** */ ******************************************************************************** */
int MatchWild(cchar *pWild, cchar *pString) int MatchWild(cchar *pWild, cchar *pString)
{ {
int ii, star; int ii, star;
skipping to change at line 5090 skipping to change at line 5087
int HashTab::Dump() int HashTab::Dump()
{ {
int ii, pos; int ii, pos;
for (ii = 0; ii < cap; ii++) for (ii = 0; ii < cap; ii++)
{ {
pos = ii * cc; pos = ii * cc;
if (table[pos] && table[pos] != -1) if (table[pos] && table[pos] != -1)
Plog(1,"%d, %s \n", ii, table + pos); Plog(0,"%d, %s \n", ii, table + pos);
if (table[pos] == -1) if (table[pos] == -1)
Plog(1,"%d, deleted \n", pos); Plog(0,"%d, deleted \n", pos);
} }
return 1; return 1;
} }
/******************************************************************************* * /******************************************************************************* *
list processing functions // replace pvlist functions list processing functions // replace pvlist functions
typedef struct { list data type typedef struct { list data type
skipping to change at line 5165 skipping to change at line 5162
if (zlist->mber) zfree(zlist->mber); if (zlist->mber) zfree(zlist->mber);
zlist->count = 0; zlist->count = 0;
zfree(zlist); zfree(zlist);
return; return;
} }
// dump zlist to stdout // dump zlist to stdout
void zlist_dump(zlist_t *zlist) void zlist_dump(zlist_t *zlist)
{ {
Plog(1,"count: %d \n",zlist->count); Plog(0,"count: %d \n",zlist->count);
for (int ii = 0; ii < zlist->count; ii++) for (int ii = 0; ii < zlist->count; ii++)
Plog(1,"%5d %s \n",ii,zlist->mber[ii]); Plog(0,"%5d %s \n",ii,zlist->mber[ii]);
Plog(1,"\n"); Plog(0,"\n");
return; return;
} }
// get zlist member count // get zlist member count
int zlist_count(zlist_t *zlist) int zlist_count(zlist_t *zlist)
{ {
return zlist->count; return zlist->count;
} }
skipping to change at line 5764 skipping to change at line 5761
appname2[cc] = 0; appname2[cc] = 0;
cc = readlink("/proc/self/exe",Busr,300); // get own program path cc = readlink("/proc/self/exe",Busr,300); // get own program path
if (cc <= 0) return 4; if (cc <= 0) return 4;
Busr[cc] = 0; // /tmp/mountpoint/usr/bin/appname Busr[cc] = 0; // /tmp/mountpoint/usr/bin/appname
pp = strstr(Busr,"/usr/"); pp = strstr(Busr,"/usr/");
if (! pp) return 4; if (! pp) return 4;
pp[4] = 0; // Busr = /tmp/mountpoint/usr/ pp[4] = 0; // Busr = /tmp/mountpoint/usr/
// if not already done, copy the current executable file to // if not already done, copy the current executable file to
// /home/<user>/.local/bin/appname-NN.N-appimage // /home/<user>/.local/bin/appname-NN.N-appimage
snprintf(appimagexe2,100,"%s/.local/bin/%s",homedir,appname1); snprintf(appimagexe2,100,"%s/.local/bin/%s",homedir,appname1);
err = stat(appimagexe1,&statB1); err = stat(appimagexe1,&statB1);
err += stat(appimagexe2,&statB2); err += stat(appimagexe2,&statB2);
if (! err) timediff = statB1.st_mtim.tv_sec - statB2.st_mtim.tv_sec; if (! err) timediff = statB1.st_mtim.tv_sec - statB2.st_mtim.tv_sec;
if (! err && timediff < 3) return 2; // not a new install if (! err && timediff < 3) return 2; // not a new install
Plog(0,"copy appimage executable file to: %s \n",appimagexe2); Plog(0,"copy appimage executable file to: %s \n",appimagexe2);
err = zshell("log","mkdir -p %s/.local/bin",homedir); err = zshell("log","mkdir -p %s/.local/bin",homedir);
err = zshell("log","cp -f -p %s %s",appimagexe1,appimagexe2); err = zshell("log","cp -f -p %s %s",appimagexe1,appimagexe2);
skipping to change at line 5939 skipping to change at line 5936
progexe = 0; progexe = 0;
cc = readlink("/proc/self/exe",buff,300); // get my executable program path cc = readlink("/proc/self/exe",buff,300); // get my executable program path
if (cc <= 0) zexit("readlink() /proc/self/exe) failed"); if (cc <= 0) zexit("readlink() /proc/self/exe) failed");
buff[cc] = 0; // readlink() quirk buff[cc] = 0; // readlink() quirk
progexe = zstrdup(buff,"zinitapp"); progexe = zstrdup(buff,"zinitapp");
err = appimage_install(zappname); // if appimage, menu integration err = appimage_install(zappname); // if appimage, menu integration
if (err == 4) if (err == 4)
Plog(0,"failed to create ~/.local/share/applications/%s.desktop \n" Plog(0,"failed to create ~/.local/share/applications/%s.desktop \n"
"desktop menu integration did not work",zappname); "desktop menu integration did not work \n",zappname);
if (argc > 1 && strstr(argv[1],"uninstall")) { // -uninstall appimage ('-' optional) if (argc > 1 && strstr(argv[1],"uninstall")) { // -uninstall appimage ('-' optional)
appimage_unstall(); // (does not return) appimage_unstall(); // (does not return)
exit(0); exit(0);
} }
if (*appimagexe1) Plog(1,"appimage: %s \n",appimagexe1); // print appimage path (container) if (*appimagexe1) Plog(1,"appimage: %s \n",appimagexe1); // print appimage path (container)
else Plog(1,"program exe: %s \n",progexe); // else executable path else Plog(1,"program exe: %s \n",progexe); // else executable path
strncpy0(zprefix,progexe,200); strncpy0(zprefix,progexe,200);
skipping to change at line 6604 skipping to change at line 6601
cchar *topic; cchar *topic;
char text2[200], weblink[200]; char text2[200], weblink[200];
static int Btab[10], maxB = 10, Bpos = 0; // last 10 links clicked static int Btab[10], maxB = 10, Bpos = 0; // last 10 links clicked
gtk_widget_grab_focus(textwidget); // necessary for some reason gtk_widget_grab_focus(textwidget); // necessary for some reason
textwidget_get_visible_lines(textwidget,vtop,vbott); // range of lines on screen textwidget_get_visible_lines(textwidget,vtop,vbott); // range of lines on screen
if (kbkey == 'r' || kbkey == 'R') // key 'R', recent topics if (kbkey == 'r' || kbkey == 'R') // key 'R', recent topics
{ {
topic = zdialog_picklist("recent",textwidget,RTopics->mber,RTopics->count) topic = popup_picklist(textwidget,(cchar **) RTopics->mber,0,
; // choose a topic // choose a topic
RTopics->count);
if (! topic) return; if (! topic) return;
for (ii = 0; ii < TN; ii++) // search docfile topics for (ii = 0; ii < TN; ii++) // search docfile topics
if (strmatchcase(topic,Tname[ii])) break; if (strmatchcase(topic,Tname[ii])) break;
if (ii == TN) return; // not found if (ii == TN) return; // not found
currline = Tline[ii]; // get line of matching topic currline = Tline[ii]; // get line of matching topic
popup_report_scroll_top(zd,currline); // scroll to topic line popup_report_scroll_top(zd,currline); // scroll to topic line
zlist_prepend(RTopics,topic,0); // add to recent topics, 1st position zlist_prepend(RTopics,topic,0); // add to recent topics, 1st position
skipping to change at line 8058 skipping to change at line 8056
vbm->menu[me].arg = name; // argument is menu name or arg if avail. vbm->menu[me].arg = name; // argument is menu name or arg if avail.
if (arg) vbm->menu[me].arg = arg; if (arg) vbm->menu[me].arg = arg;
vbm->menu[me].pixbuf = 0; vbm->menu[me].pixbuf = 0;
if (icon) { // if icon is named, get pixbuf if (icon) { // if icon is named, get pixbuf
*iconpath = 0; *iconpath = 0;
strncatv(iconpath,199,zfuncs::zimagedir,"/",icon,null); strncatv(iconpath,199,zfuncs::zimagedir,"/",icon,null);
pixbuf = gdk_pixbuf_new_from_file_at_scale(iconpath,iconww,iconhh,1,&gerro r); pixbuf = gdk_pixbuf_new_from_file_at_scale(iconpath,iconww,iconhh,1,&gerro r);
if (pixbuf) vbm->menu[me].pixbuf = pixbuf; if (pixbuf) vbm->menu[me].pixbuf = pixbuf;
else Plog(0,"Vmenu no icon: %s \n",iconpath); else Plog(1,"Vmenu no icon: %s \n",iconpath);
} }
if (me == 0) vbm->ymax = margin; // first menu, top position if (me == 0) vbm->ymax = margin; // first menu, top position
vbm->menu[me].iconx = 0; vbm->menu[me].iconx = 0;
vbm->menu[me].icony = 0; vbm->menu[me].icony = 0;
vbm->menu[me].namex = 0; vbm->menu[me].namex = 0;
vbm->menu[me].namey = 0; vbm->menu[me].namey = 0;
if (icon) { if (icon) {
skipping to change at line 9139 skipping to change at line 9137
zd->widget[iiw].wrap = wrap; zd->widget[iiw].wrap = wrap;
zd->widget[iiw].widget = 0; zd->widget[iiw].widget = 0;
zd->widget[iiw+1].type = 0; // set new EOF marker zd->widget[iiw+1].type = 0; // set new EOF marker
if (strmatchV(type,"dialog","hbox","vbox","hsep","vsep","frame","scrwin", if (strmatchV(type,"dialog","hbox","vbox","hsep","vsep","frame","scrwin",
"label","link","zentry","zedit","text","report", "label","link","zentry","zedit","text","report",
"button","zbutton","togbutt","check","radio", "button","zbutton","togbutt","check","radio",
"imagebutt","colorbutt","combo","spin","zspin", "imagebutt","colorbutt","combo","spin","zspin",
"hscale","hscale2","vscale","icon","image",null) == 0) { "hscale","hscale2","vscale","icon","image",null) == 0) {
Plog(0,"*** zdialog, bad widget type: %s \n",type); Plog(0,"zdialog, bad widget type: %s \n",type);
return 0; return 0;
} }
for (iip = iiw-1; iip >= 0; iip--) // find parent (container) widget for (iip = iiw-1; iip >= 0; iip--) // find parent (container) widget
if (strmatch(pname,zd->widget[iip].wname)) break; if (strmatch(pname,zd->widget[iip].wname)) break;
if (iip < 0) zappcrash("zdialog, no parent for widget: %s",wname); if (iip < 0) zappcrash("zdialog, no parent for widget: %s",wname);
pwidget = zd->widget[iip].widget; // parent widget, type pwidget = zd->widget[iip].widget; // parent widget, type
ptype = zd->widget[iip].type; ptype = zd->widget[iip].type;
skipping to change at line 9469 skipping to change at line 9467
if (zd == zdialog_list[ii]) break; if (zd == zdialog_list[ii]) break;
if (ii == zdialog_count) { if (ii == zdialog_count) {
printf("*** zdialog not in valid list %s \n",title); printf("*** zdialog not in valid list %s \n",title);
return 0; return 0;
} }
ok = 1; ok = 1;
if ((zd->sentinel1 & 0xFFFF0000) != zdsentinel) ok = 0; if ((zd->sentinel1 & 0xFFFF0000) != zdsentinel) ok = 0;
if (zd->sentinel2 != zd->sentinel1) ok = 0; if (zd->sentinel2 != zd->sentinel1) ok = 0;
if (! ok) { if (! ok) {
Plog(0,"*** zdialog sentinel invalid %s \n",title); Plog(0,"zdialog sentinel invalid %s \n",title);
return 0; return 0;
} }
if (title && ! strmatch(title,zd->title)) { if (title && ! strmatch(title,zd->title)) {
Plog(0,"*** zdialog title invalid %s \n",title); Plog(0,"zdialog title invalid %s \n",title);
return 0; return 0;
} }
return 1; return 1;
} }
// return 1/0 if zdialog is valid/invalid // return 1/0 if zdialog is valid/invalid
// silent version to use when zdialog is possibly destroyed // silent version to use when zdialog is possibly destroyed
int zdialog_valid2(zdialog *zd, cchar *title) int zdialog_valid2(zdialog *zd, cchar *title)
skipping to change at line 9506 skipping to change at line 9504
if (title && ! strmatch(title,zd->title)) return 0; if (title && ! strmatch(title,zd->title)) return 0;
return 1; return 1;
} }
// find zdialog widget from zdialog and widget name // find zdialog widget from zdialog and widget name
int zdialog_find_widget(zdialog *zd, cchar *wname) int zdialog_find_widget(zdialog *zd, cchar *wname)
{ {
if (! zdialog_valid(zd)) return 0; if (! zdialog_valid(zd)) {
Plog(0,"invalid zdialog %p \n",zd);
return 0;
}
for (int ii = 0; zd->widget[ii].type; ii++) for (int ii = 0; zd->widget[ii].type; ii++)
if (strmatch(zd->widget[ii].wname,wname)) return ii; if (strmatch(zd->widget[ii].wname,wname)) return ii;
Plog(0,"*** zdialog bad widget name: %s \n",wname);
Plog(0,"zdialog bad widget name: %s \n",wname);
return 0; return 0;
} }
// get GTK widget from zdialog and widget name // get GTK widget from zdialog and widget name
GtkWidget * zdialog_gtkwidget(zdialog *zd, cchar *wname) GtkWidget * zdialog_gtkwidget(zdialog *zd, cchar *wname)
{ {
if (strmatch(wname,"dialog")) return zd->widget[0].widget; if (strmatch(wname,"dialog")) return zd->widget[0].widget;
int ii = zdialog_find_widget(zd,wname); int ii = zdialog_find_widget(zd,wname);
if (ii) return zd->widget[ii].widget; if (ii) return zd->widget[ii].widget;
skipping to change at line 9771 skipping to change at line 9774
// set new limits for a numeric data entry widget (spin, zspin, hscale, vscale) // set new limits for a numeric data entry widget (spin, zspin, hscale, vscale)
int zdialog_set_limits(zdialog *zd, cchar *wname, double min, double max) int zdialog_set_limits(zdialog *zd, cchar *wname, double min, double max)
{ {
GtkWidget *widget; GtkWidget *widget;
cchar *type; cchar *type;
int iiw; int iiw;
iiw = zdialog_find_widget(zd,wname); iiw = zdialog_find_widget(zd,wname);
if (! iiw) { if (! iiw) {
Plog(0,"*** zdialog_set_limits, %s not found \n",wname); Plog(0,"zdialog_set_limits, %s not found \n",wname);
return 0; return 0;
} }
widget = zd->widget[iiw].widget; widget = zd->widget[iiw].widget;
type = zd->widget[iiw].type; type = zd->widget[iiw].type;
if (*type == 's') if (*type == 's')
gtk_spin_button_set_range(GTK_SPIN_BUTTON(widget),min,max); gtk_spin_button_set_range(GTK_SPIN_BUTTON(widget),min,max);
if (*type == 'h' || *type == 'v') if (*type == 'h' || *type == 'v')
skipping to change at line 9824 skipping to change at line 9827
// lval <= nval <= hval // lval <= nval <= hval
int zdialog_rescale(zdialog *zd, cchar *wname, float lval, float nval, float hva l) int zdialog_rescale(zdialog *zd, cchar *wname, float lval, float nval, float hva l)
{ {
int iiw; int iiw;
iiw = zdialog_find_widget(zd,wname); iiw = zdialog_find_widget(zd,wname);
if (! iiw) return 0; if (! iiw) return 0;
if (lval > nval || nval > hval) { if (lval > nval || nval > hval) {
Plog(0,"*** zdialog_rescale, bad data: %s \n",wname); Plog(0,"zdialog_rescale, bad data: %s \n",wname);
return 0; return 0;
} }
zd->widget[iiw].rescale = 1; zd->widget[iiw].rescale = 1;
zd->widget[iiw].lval = lval; zd->widget[iiw].lval = lval;
zd->widget[iiw].nval = nval; zd->widget[iiw].nval = nval;
zd->widget[iiw].hval = hval; zd->widget[iiw].hval = hval;
return 1; return 1;
} }
skipping to change at line 9938 skipping to change at line 9941
if (zd->widget[ii].widget == widget) goto found_widget; if (zd->widget[ii].widget == widget) goto found_widget;
for (ii = 1; zd->widget[ii].type; ii++) { // failed, test if buffer for (ii = 1; zd->widget[ii].type; ii++) { // failed, test if buffer
if (strmatchV(zd->widget[ii].type,"zedit","zentry",null)) { // of text view widget if (strmatchV(zd->widget[ii].type,"zedit","zentry",null)) { // of text view widget
textView = GTK_TEXT_VIEW(zd->widget[ii].widget); textView = GTK_TEXT_VIEW(zd->widget[ii].widget);
textBuff = gtk_text_view_get_buffer(textView); textBuff = gtk_text_view_get_buffer(textView);
if (widget == (GtkWidget *) textBuff) goto found_widget; if (widget == (GtkWidget *) textBuff) goto found_widget;
} }
} }
Plog(0,"*** zdialog event ignored: %s \n",zd->title); // not found, ignore event Plog(0,"zdialog event ignored: %s \n",zd->title); // not found, ignore event
zd->disabled = 0; zd->disabled = 0;
return 1; return 1;
found_widget: found_widget:
wname = zd->widget[ii].wname; wname = zd->widget[ii].wname;
wtype = zd->widget[ii].type; wtype = zd->widget[ii].type;
wdata = 0; wdata = 0;
Plog(2,"dialog: %s event: %s \n",zd->title,wname); // Floglevel=2 to log dialog inputs Plog(2,"dialog: %s event: %s \n",zd->title,wname); // Floglevel=2 to log dialog inputs
skipping to change at line 10501 skipping to change at line 10504
if (zd->widget[ii].zlist) zlist_delete(zd->widget[ii].zlist); // free combo box zlist if (zd->widget[ii].zlist) zlist_delete(zd->widget[ii].zlist); // free combo box zlist
} }
for (ii = 0; ii < zdialog_count; ii++) // remove from valid zdialog list for (ii = 0; ii < zdialog_count; ii++) // remove from valid zdialog list
if (zd == zdialog_list[ii]) break; if (zd == zdialog_list[ii]) break;
if (ii < zdialog_count) { if (ii < zdialog_count) {
zdialog_count--; zdialog_count--;
for (NOP; ii < zdialog_count; ii++) // pack down list for (NOP; ii < zdialog_count; ii++) // pack down list
zdialog_list[ii] = zdialog_list[ii+1]; zdialog_list[ii] = zdialog_list[ii+1];
} }
else Plog(0,"*** zdialog_free(), not in zdialog_list \n"); else Plog(0,"zdialog_free(), not in zdialog_list \n");
zfree(zd); // free zdialog memory zfree(zd); // free zdialog memory
zd = 0; // caller pointer = null zd = 0; // caller pointer = null
return 1; return 1;
} }
// Wait for a dialog to complete or be destroyed. This is a zmainloop() loop. // Wait for a dialog to complete or be destroyed. This is a zmainloop() loop.
// The returned status is the button 1-N used to complete the dialog, or negati ve // The returned status is the button 1-N used to complete the dialog, or negati ve
// if the dialog was destroyed with [x] or otherwise by GTK. If the status was 1-N and // if the dialog was destroyed with [x] or otherwise by GTK. If the status was 1-N and
// the dialog will be kept active, set zd->zstat = 0 to restore the active stat e. // the dialog will be kept active, set zd->zstat = 0 to restore the active stat e.
skipping to change at line 10950 skipping to change at line 10953
fclose(fid); fclose(fid);
Nzdposn = ii; Nzdposn = ii;
return Nzdposn; return Nzdposn;
} }
if (strmatch(action,"save")) // save dialog positions table to file if (strmatch(action,"save")) // save dialog positions table to file
{ {
fid = fopen(posfile,"w"); fid = fopen(posfile,"w");
if (! fid) { if (! fid) {
Plog(0,"*** cannot write zdialog_geometry file \n"); Plog(0,"cannot write zdialog_geometry file \n");
return 0; return 0;
} }
for (ii = 0; ii < Nzdposn; ii++) { for (ii = 0; ii < Nzdposn; ii++) {
fprintf(fid,"%s || %0.1f %0.1f %d %d \n", // dialog-title || xpos ypos xsize ysize fprintf(fid,"%s || %0.1f %0.1f %d %d \n", // dialog-title || xpos ypos xsize ysize
zdposn[ii].wintitle, zdposn[ii].wintitle,
zdposn[ii].xpos, zdposn[ii].ypos, zdposn[ii].xpos, zdposn[ii].ypos,
zdposn[ii].xsize, zdposn[ii].ysize); zdposn[ii].xsize, zdposn[ii].ysize);
} }
fclose(fid); fclose(fid);
return Nzdposn; return Nzdposn;
} }
Plog(0,"*** zdialog_geometry bad action: %s \n",action); Plog(0,"zdialog_geometry bad action: %s \n",action);
return 0; return 0;
} }
// Set the initial or new zdialog window position from "posn". // Set the initial or new zdialog window position from "posn".
// Called by zdialog_run(). Private function. // Called by zdialog_run(). Private function.
// null: window manager decides // null: window manager decides
// "mouse" put dialog at mouse position // "mouse" put dialog at mouse position
// "desktop" center dialog in desktop window // "desktop" center dialog in desktop window
// "parent" center dialog in parent window // "parent" center dialog in parent window
// "save" use the same position last set by the user // "save" use the same position last set by the user
skipping to change at line 11026 skipping to change at line 11029
else { else {
gtk_window_get_position(GTK_WINDOW(parent),&ppx,&ppy); // parent window NW corner gtk_window_get_position(GTK_WINDOW(parent),&ppx,&ppy); // parent window NW corner
gtk_window_get_size(GTK_WINDOW(parent),&pww,&phh); // parent window size gtk_window_get_size(GTK_WINDOW(parent),&pww,&phh); // parent window size
} }
if (strmatch(posn,"save")) // use last saved window position if (strmatch(posn,"save")) // use last saved window position
{ {
zd->saveposn = 1; // set flag for zdialog_free() zd->saveposn = 1; // set flag for zdialog_free()
pp = (char *) gtk_window_get_title(GTK_WINDOW(dialog)); // get window title, used as ID pp = (char *) gtk_window_get_title(GTK_WINDOW(dialog)); // get window title, used as ID
if (! pp) return; if (! pp || strlen(pp) < 2) goto center_parent;
if (strlen(pp) < 2) return; // 22.31
strncpy0(wintitle,pp,64); // window title, < 64 chars. strncpy0(wintitle,pp,64); // window title, < 64 chars.
for (ii = 0; ii < Nzdposn; ii++) // search table for title for (ii = 0; ii < Nzdposn; ii++) // search table for title
if (strmatch(wintitle,zdposn[ii].wintitle)) break; if (strmatch(wintitle,zdposn[ii].wintitle)) break;
if (ii == Nzdposn) { if (ii == Nzdposn) goto center_parent;
// not found - zdialog_destroy() will add // not found - zdialog_destroy() will add
zdpx = ppx + 0.8 * pww;
// supply reasonable defaults
zdpy = ppx + 0.2 * phh;
gtk_window_get_size(GTK_WINDOW(dialog),&xsize,&ysize);
// use current size
}
else {
zdpx = ppx + 0.01 * zdposn[ii].xpos * pww;
// set position for dialog window
zdpy = ppy + 0.01 * zdposn[ii].ypos * phh;
xsize = zdposn[ii].xsize;
// set size
ysize = zdposn[ii].ysize;
}
zdpx = ppx + 0.01 * zdposn[ii].xpos * pww;
// set position for dialog window
zdpy = ppy + 0.01 * zdposn[ii].ypos * phh;
xsize = zdposn[ii].xsize;
// set size
ysize = zdposn[ii].ysize;
gtk_window_move(GTK_WINDOW(dialog),zdpx,zdpy); gtk_window_move(GTK_WINDOW(dialog),zdpx,zdpy);
gtk_window_resize(GTK_WINDOW(dialog),xsize,ysize); gtk_window_resize(GTK_WINDOW(dialog),xsize,ysize);
return; return;
} }
else // "nn/nn" // position from caller else // "nn/nn" // position from caller
{ {
ii = sscanf(posn,"%f/%f",&xpos,&ypos); // parse "nn/nn" ii = sscanf(posn,"%f/%f",&xpos,&ypos); // parse "nn/nn"
if (ii != 2) return; if (ii != 2) goto center_parent;
zdpx = ppx + 0.01 * xpos * pww; // position for dialog window zdpx = ppx + 0.01 * xpos * pww; // position for dialog window
zdpy = ppy + 0.01 * ypos * phh; zdpy = ppy + 0.01 * ypos * phh;
gtk_window_move(GTK_WINDOW(dialog),zdpx,zdpy); gtk_window_move(GTK_WINDOW(dialog),zdpx,zdpy);
return; return;
} }
center_parent:
// center on parent window 22.31
gtk_window_set_position(GTK_WINDOW(dialog),GTK_WIN_POS_CENTER_ON_PARENT);
return;
} }
// If the dialog window position is "save" then save // If the dialog window position is "save" then save
// its position WRT parent or desktop for next use. // its position WRT parent or desktop for next use.
// called by zdialog_destroy(). Private function. // called by zdialog_destroy(). Private function.
void zdialog_save_position(zdialog *zd) void zdialog_save_position(zdialog *zd)
{ {
using namespace zdposn_names; using namespace zdposn_names;
skipping to change at line 11181 skipping to change at line 11183
pp = fgets_trim(buff,ccmax2,fid,1); // read next zdialog title record pp = fgets_trim(buff,ccmax2,fid,1); // read next zdialog title record
if (! pp) break; if (! pp) break;
if (! strmatchN(pp,"zdialog == ",11)) continue; if (! strmatchN(pp,"zdialog == ",11)) continue;
strncpy0(zdtitle,pp+11,ccmax1); // save new zdialog title strncpy0(zdtitle,pp+11,ccmax1); // save new zdialog title
pp = fgets_trim(buff,ccmax2,fid,1); // read widget count pp = fgets_trim(buff,ccmax2,fid,1); // read widget count
if (! pp) break; if (! pp) break;
Nw = atoi(pp); Nw = atoi(pp);
if (Nw < 1 || Nw > Nwmax) { if (Nw < 1 || Nw > Nwmax) {
Plog(0,"*** zdialog_inputs() bad data: %s \n",zdtitle); Plog(0,"zdialog_inputs() bad data: %s \n",zdtitle);
continue; continue;
} }
for (ii = 0; ii < Nw; ii++) // read widget data recs for (ii = 0; ii < Nw; ii++) // read widget data recs
{ {
pp = fgets_trim(buff,ccmax2,fid,1); pp = fgets_trim(buff,ccmax2,fid,1);
if (! pp) break; if (! pp) break;
pp1 = pp; pp1 = pp;
pp2 = strstr(pp1," =="); pp2 = strstr(pp1," ==");
if (! pp2) break; // widget has no data if (! pp2) break; // widget has no data
skipping to change at line 11206 skipping to change at line 11208
cc2 = strlen(pp2); cc2 = strlen(pp2);
if (cc1 < 1 || cc1 >= ccmax1) break; if (cc1 < 1 || cc1 >= ccmax1) break;
if (cc2 < 1) pp2 = (char *) ""; if (cc2 < 1) pp2 = (char *) "";
if (cc2 >= ccmax2) break; // do not copy large inputs if (cc2 >= ccmax2) break; // do not copy large inputs
strcpy(wname[ii],pp1); // save widget name and data strcpy(wname[ii],pp1); // save widget name and data
strcpy(wdata2,pp2); strcpy(wdata2,pp2);
repl_1str(wdata2,wdata[ii],"\\n","\n"); // replace "\n" with newline chars. repl_1str(wdata2,wdata[ii],"\\n","\n"); // replace "\n" with newline chars.
} }
if (ii < Nw) { if (ii < Nw) {
Plog(0,"*** zdialog_inputs() bad data: %s \n",zdtitle); Plog(0,"zdialog_inputs() bad data: %s \n",zdtitle);
continue; continue;
} }
if (Nzd == Nzdmax) { if (Nzd == Nzdmax) {
Plog(0,"*** zdialog_inputs() too many dialogs \n"); Plog(0,"zdialog_inputs() too many dialogs \n");
break; break;
} }
zdinputs[Nzd].zdtitle = zstrdup(zdtitle,"zdialog_inputs"); // save acculumated zdialog data zdinputs[Nzd].zdtitle = zstrdup(zdtitle,"zdialog_inputs"); // save acculumated zdialog data
zdinputs[Nzd].Nw = Nw; zdinputs[Nzd].Nw = Nw;
cc = Nw * sizeof(char *); cc = Nw * sizeof(char *);
zdinputs[Nzd].wname = (char **) zmalloc(cc,"zdialog_inputs"); zdinputs[Nzd].wname = (char **) zmalloc(cc,"zdialog_inputs");
zdinputs[Nzd].wdata = (char **) zmalloc(cc,"zdialog_inputs"); zdinputs[Nzd].wdata = (char **) zmalloc(cc,"zdialog_inputs");
for (ii = 0; ii < Nw; ii++) { for (ii = 0; ii < Nw; ii++) {
zdinputs[Nzd].wname[ii] = zstrdup(wname[ii],"zdialog_inputs"); zdinputs[Nzd].wname[ii] = zstrdup(wname[ii],"zdialog_inputs");
skipping to change at line 11236 skipping to change at line 11238
} }
fclose(fid); fclose(fid);
return Nzd; return Nzd;
} }
if (strmatch(action,"save")) // save dialog input fields to its file if (strmatch(action,"save")) // save dialog input fields to its file
{ {
fid = fopen(zdinputsfile,"w"); fid = fopen(zdinputsfile,"w");
if (! fid) { if (! fid) {
Plog(0,"*** zdialog_inputs() cannot write file \n"); Plog(0,"zdialog_inputs() cannot write file \n");
return 0; return 0;
} }
for (ii = 0; ii < Nzd; ii++) for (ii = 0; ii < Nzd; ii++)
{ {
fprintf(fid,"zdialog == %s \n",zdinputs[ii].zdtitle); // zdialog == zdialog title fprintf(fid,"zdialog == %s \n",zdinputs[ii].zdtitle); // zdialog == zdialog title
Nw = zdinputs[ii].Nw; Nw = zdinputs[ii].Nw;
fprintf(fid,"%d \n",Nw); // widget count fprintf(fid,"%d \n",Nw); // widget count
for (jj = 0; jj < Nw; jj++) { for (jj = 0; jj < Nw; jj++) {
pp1 = zdinputs[ii].wname[jj]; // widget name == widget data pp1 = zdinputs[ii].wname[jj]; // widget name == widget data
skipping to change at line 11258 skipping to change at line 11260
repl_1str(pp2,wdata2,"\n","\\n"); // replace newline chars. with "\n" repl_1str(pp2,wdata2,"\n","\\n"); // replace newline chars. with "\n"
fprintf(fid,"%s == %s \n",pp1,wdata2); fprintf(fid,"%s == %s \n",pp1,wdata2);
} }
fprintf(fid,"\n"); fprintf(fid,"\n");
} }
fclose(fid); fclose(fid);
return Nzd; return Nzd;
} }
Plog(0,"*** zdialog_inputs bad action: %s \n",action); Plog(0,"zdialog_inputs bad action: %s \n",action);
return 0; return 0;
} }
// Save dialog user input fields when a dialog is finished. // Save dialog user input fields when a dialog is finished.
// Called automatically by zdialog_free(). Private function. // Called automatically by zdialog_free(). Private function.
int zdialog_save_inputs(zdialog *zd) int zdialog_save_inputs(zdialog *zd)
{ {
using namespace zdinputs_names; using namespace zdinputs_names;
skipping to change at line 11299 skipping to change at line 11301
zfree(zdinputs[ii].wdata[jj]); zfree(zdinputs[ii].wdata[jj]);
} }
zfree(zdinputs[ii].wname); zfree(zdinputs[ii].wname);
zfree(zdinputs[ii].wdata); zfree(zdinputs[ii].wdata);
Nzd--; // decr. zdialog count Nzd--; // decr. zdialog count
for (NOP; ii < Nzd; ii++) // pack down the rest for (NOP; ii < Nzd; ii++) // pack down the rest
zdinputs[ii] = zdinputs[ii+1]; zdinputs[ii] = zdinputs[ii+1];
} }
if (Nzd == Nzdmax) { if (Nzd == Nzdmax) {
Plog(0,"*** zdialog_save_inputs, too many zdialogs \n"); Plog(0,"zdialog_save_inputs, too many zdialogs \n");
return 0; return 0;
} }
ii = Nzd; // next zdinputs table entry ii = Nzd; // next zdinputs table entry
for (Nw = 0, jj = 1; zd->widget[jj].type; jj++) { // count zdialog widgets for (Nw = 0, jj = 1; zd->widget[jj].type; jj++) { // count zdialog widgets
wnamex = (char *) zd->widget[jj].wname; wnamex = (char *) zd->widget[jj].wname;
type = (char *) zd->widget[jj].type; type = (char *) zd->widget[jj].type;
if (strstr(skipwidgets,type)) // skip non-input widgets if (strstr(skipwidgets,type)) // skip non-input widgets
if (! strstr(skipexceptions,wnamex)) continue; if (! strstr(skipexceptions,wnamex)) continue;
Nw++; Nw++;
} }
if (! Nw) return 0; // no input widgets if (! Nw) return 0; // no input widgets
if (Nw > Nwmax) { if (Nw > Nwmax) {
Plog(0,"*** zdialog_inputs() bad data: %s \n",zdtitle); Plog(0,"zdialog_inputs() bad data: %s \n",zdtitle);
return 0; return 0;
} }
zdinputs[ii].zdtitle = zstrdup(zdtitle,"zdialog_save"); // set zdialog title zdinputs[ii].zdtitle = zstrdup(zdtitle,"zdialog_save"); // set zdialog title
cc = Nw * sizeof(char *); // allocate pointers for widgets cc = Nw * sizeof(char *); // allocate pointers for widgets
zdinputs[ii].wname = (char **) zmalloc(cc,"zdialog_save"); zdinputs[ii].wname = (char **) zmalloc(cc,"zdialog_save");
zdinputs[ii].wdata = (char **) zmalloc(cc,"zdialog_save"); zdinputs[ii].wdata = (char **) zmalloc(cc,"zdialog_save");
for (Nw = 0, jj = 1; zd->widget[jj].type; jj++) { // add widget names and data for (Nw = 0, jj = 1; zd->widget[jj].type; jj++) { // add widget names and data
skipping to change at line 11559 skipping to change at line 11561
zdialog_destroy(zd); zdialog_destroy(zd);
zd->zstat = KBkey; zd->zstat = KBkey;
return 1; return 1;
} }
return 0; return 0;
} }
/******************************************************************************* */ /******************************************************************************* */
// popup dialog with pick list
// returns user choice, or null if dialog cancel
cchar * zdialog_picklist(cchar *title, GtkWidget *parent, char **picklist, int N
pick)
{
int zdialog_picklist_event(zdialog *zd, cchar *event);
static char selection[100];
zdialog *zd;
int ii;
zd = zdialog_new(title,parent,0);
zdialog_add_widget(zd,"combo","combo","dialog");
for (ii = 0; ii < Npick; ii++)
zdialog_stuff(zd,"combo",picklist[ii]);
zdialog_stuff(zd,"combo","");
// no active entry
zdialog_set_modal(zd);
// compensate GTK problem 22.20
zdialog_run(zd,0,"mouse");
zdialog_combo_popup(zd,"combo");
*selection = 0;
while (true)
{
zmainsleep(0.1);
if (! zdialog_valid2(zd)) break;
zdialog_fetch(zd,"combo",selection,100);
if (*selection) break;
}
if (zdialog_valid2(zd)) zdialog_free(zd);
if (*selection) return selection;
return 0;
}
/*******************************************************************************
*/
// popup a list of characters and text strings for insertion // popup a list of characters and text strings for insertion
// into the currently active GtkTextView widget // into the currently active GtkTextView widget
char popup_text_textfile[XFCC]; char popup_text_textfile[XFCC];
void zdialog_popup_text(cchar *textfile, GtkWidget *parent) // 22.15 void zdialog_popup_text(cchar *textfile, GtkWidget *parent) // 22.15
{ {
void popup_text_clickfunc(GtkWidget *poptext, int line, int posn, int kbkey); void popup_text_clickfunc(GtkWidget *poptext, int line, int posn, int kbkey);
zdialog *zd; zdialog *zd;
skipping to change at line 11643 skipping to change at line 11608
{ {
using namespace zfuncs; using namespace zfuncs;
char *pp, dlim; char *pp, dlim;
int cc; int cc;
GtkWindow *window; GtkWindow *window;
GtkTextBuffer *textbuffer; GtkTextBuffer *textbuffer;
GtkWidget *widget; GtkWidget *widget;
if (kbkey == 'E') { // [Edit] 22.16 if (kbkey == 'E') { // [Edit] 22.16
zshell("log ack","xdg-open %s",popup_text_textfile); zshell("ack","xdg-open %s",popup_text_textfile);
return; return;
} }
if (line < 0 || posn < 0) return; if (line < 0 || posn < 0) return;
pp = textwidget_word(poptext,line,posn," ",dlim); pp = textwidget_word(poptext,line,posn," ",dlim);
if (! pp) return; if (! pp) return;
cc = strlen(pp); cc = strlen(pp);
if (cc < 1 || cc > 100) return; if (cc < 1 || cc > 100) return;
Plog(1,"insert %s \n",pp); Plog(2,"insert %s \n",pp);
if (! curr_textview_widget) return; if (! curr_textview_widget) return;
if (! GTK_IS_TEXT_VIEW(curr_textview_widget)) return; if (! GTK_IS_TEXT_VIEW(curr_textview_widget)) return;
window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(curr_textview_widget)) ); window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(curr_textview_widget)) );
if (! window) return; if (! window) return;
widget = gtk_window_get_focus(window); widget = gtk_window_get_focus(window);
if (! widget) return; if (! widget) return;
if (widget != GTK_WIDGET(curr_textview_widget)) return; if (widget != GTK_WIDGET(curr_textview_widget)) return;
skipping to change at line 11752 skipping to change at line 11717
int popup_report_dialog_event(zdialog *zd, cchar *event) int popup_report_dialog_event(zdialog *zd, cchar *event)
{ {
textwidget_callbackfunc_t *CBfunc; textwidget_callbackfunc_t *CBfunc;
GtkWidget *mText; GtkWidget *mText;
static char findtext[40] = ""; static char findtext[40] = "";
int linem, line1, line2; int linem, line1, line2;
zdialog *zdf; zdialog *zdf;
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return 1; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return 1; }
if (strmatch(event,"focus")) return 0; if (strmatch(event,"focus")) return 0;
if (zd->zstat) { // [x] cancel or escape, kill dialog if (zd->zstat) { // [x] cancel or escape, kill dialog
zdialog_free(zd); zdialog_free(zd);
return 1; return 1;
} }
if (strmatch(event,"Hide")) { // [Hide] hide dialog 22.15 if (strmatch(event,"Hide")) { // [Hide] hide dialog 22.15
zdialog_show(zd,0); zdialog_show(zd,0);
skipping to change at line 11821 skipping to change at line 11786
} }
// write a non-scrolling header line // write a non-scrolling header line
void popup_report_header(zdialog *zd, int bold, cchar *format, ...) void popup_report_header(zdialog *zd, int bold, cchar *format, ...)
{ {
va_list arglist; va_list arglist;
char message[1000]; char message[1000];
GtkWidget *mHead; GtkWidget *mHead;
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
va_start(arglist,format); va_start(arglist,format);
vsnprintf(message,999,format,arglist); vsnprintf(message,999,format,arglist);
va_end(arglist); va_end(arglist);
mHead = zdialog_gtkwidget(zd,"header"); mHead = zdialog_gtkwidget(zd,"header");
textwidget_append(mHead,bold,message); textwidget_append(mHead,bold,message);
gtk_widget_set_visible(mHead,1); gtk_widget_set_visible(mHead,1);
return; return;
} }
// write a new text line at the end // write a new text line at the end
void popup_report_write(zdialog *zd, int bold, cchar *format, ...) void popup_report_write(zdialog *zd, int bold, cchar *format, ...)
{ {
va_list arglist; va_list arglist;
char message[1000]; char message[1000];
GtkWidget *mText; GtkWidget *mText;
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
va_start(arglist,format); va_start(arglist,format);
vsnprintf(message,999,format,arglist); vsnprintf(message,999,format,arglist);
va_end(arglist); va_end(arglist);
mText = zdialog_gtkwidget(zd,"text"); mText = zdialog_gtkwidget(zd,"text");
textwidget_append(mText,bold,"%s",message); textwidget_append(mText,bold,"%s",message);
return; return;
} }
// write a new text line at the end, scroll down to end // write a new text line at the end, scroll down to end
void popup_report_write2(zdialog *zd, int bold, cchar *format, ...) void popup_report_write2(zdialog *zd, int bold, cchar *format, ...)
{ {
va_list arglist; va_list arglist;
char message[1000]; char message[1000];
GtkWidget *mText; GtkWidget *mText;
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
va_start(arglist,format); va_start(arglist,format);
vsnprintf(message,999,format,arglist); vsnprintf(message,999,format,arglist);
va_end(arglist); va_end(arglist);
mText = zdialog_gtkwidget(zd,"text"); mText = zdialog_gtkwidget(zd,"text");
textwidget_append2(mText,bold,"%s",message); textwidget_append2(mText,bold,"%s",message);
return; return;
} }
skipping to change at line 11920 skipping to change at line 11885
void popup_report_insert(zdialog *zd, int bold, int line, cchar *format, ...) void popup_report_insert(zdialog *zd, int bold, int line, cchar *format, ...)
{ {
va_list arglist; va_list arglist;
char message[1000]; char message[1000];
GtkWidget *mText; GtkWidget *mText;
va_start(arglist,format); va_start(arglist,format);
vsnprintf(message,999,format,arglist); vsnprintf(message,999,format,arglist);
va_end(arglist); va_end(arglist);
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
mText = zdialog_gtkwidget(zd,"text"); mText = zdialog_gtkwidget(zd,"text");
textwidget_insert(mText,bold,line,message); textwidget_insert(mText,bold,line,message);
return; return;
} }
// replace a given line // replace a given line
void popup_report_replace(zdialog *zd, int bold, int line, cchar *format, ...) void popup_report_replace(zdialog *zd, int bold, int line, cchar *format, ...)
{ {
va_list arglist; va_list arglist;
char message[1000]; char message[1000];
GtkWidget *mText; GtkWidget *mText;
va_start(arglist,format); va_start(arglist,format);
vsnprintf(message,999,format,arglist); vsnprintf(message,999,format,arglist);
va_end(arglist); va_end(arglist);
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
mText = zdialog_gtkwidget(zd,"text"); mText = zdialog_gtkwidget(zd,"text");
textwidget_replace(mText,bold,line,message); textwidget_replace(mText,bold,line,message);
return; return;
} }
// delete a given line // delete a given line
void popup_report_delete(zdialog *zd, int line) void popup_report_delete(zdialog *zd, int line)
{ {
skipping to change at line 11962 skipping to change at line 11927
return; return;
} }
// find first line of text containing characters matching input string // find first line of text containing characters matching input string
// search is from line1 to end, then from 0 to line1-1 // search is from line1 to end, then from 0 to line1-1
// returns first matching line or -1 if none // returns first matching line or -1 if none
// comparison is not case sensitive // comparison is not case sensitive
int popup_report_find(zdialog *zd, char *matchtext, int line1) int popup_report_find(zdialog *zd, char *matchtext, int line1)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return 1; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return 1; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
return textwidget_find(mText,matchtext,line1); return textwidget_find(mText,matchtext,line1);
} }
// insert a pixbuf image after a given line // insert a pixbuf image after a given line
void popup_report_insert_pixbuf(zdialog *zd, int line, GdkPixbuf *pixbuf) void popup_report_insert_pixbuf(zdialog *zd, int line, GdkPixbuf *pixbuf)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_insert_pixbuf(mText,line,pixbuf); textwidget_insert_pixbuf(mText,line,pixbuf);
return; return;
} }
// scroll to bring a given line into the report window // scroll to bring a given line into the report window
void popup_report_scroll(zdialog *zd, int line) void popup_report_scroll(zdialog *zd, int line)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_scroll(mText,line); textwidget_scroll(mText,line);
return; return;
} }
// scroll to bring a given line to the top of the report window // scroll to bring a given line to the top of the report window
void popup_report_scroll_top(zdialog *zd, int line) void popup_report_scroll_top(zdialog *zd, int line)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_scroll_top(mText,line); textwidget_scroll_top(mText,line);
return; return;
} }
// get the range of visible lines in the report window // get the range of visible lines in the report window
void popup_report_get_visible_lines(zdialog *zd, int &vtop, int &vbott) void popup_report_get_visible_lines(zdialog *zd, int &vtop, int &vbott)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_get_visible_lines(mText,vtop,vbott); textwidget_get_visible_lines(mText,vtop,vbott);
return; return;
} }
// retrieve a given line and optionally strip the trailing \n // retrieve a given line and optionally strip the trailing \n
char * popup_report_line(zdialog *zd, int line, int strip) char * popup_report_line(zdialog *zd, int line, int strip)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return 0; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return 0; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
return textwidget_line(mText,line,strip); return textwidget_line(mText,line,strip);
} }
// retrieve the word starting at a given position in a given line // retrieve the word starting at a given position in a given line
char * popup_report_word(zdialog *zd, int line, int posn, cchar *dlims, char &en d) char * popup_report_word(zdialog *zd, int line, int posn, cchar *dlims, char &en d)
{ {
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
return textwidget_word(mText,line,posn,dlims,end); return textwidget_word(mText,line,posn,dlims,end);
} }
// highlight a given line of text // highlight a given line of text
void popup_report_highlight_line(zdialog *zd, int line) void popup_report_highlight_line(zdialog *zd, int line)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_highlight_line(mText,line); textwidget_highlight_line(mText,line);
return; return;
} }
// highlight the text at a given position and length in a given line // highlight the text at a given position and length in a given line
void popup_report_highlight_word(zdialog *zd, int line, int posn, int cc) void popup_report_highlight_word(zdialog *zd, int line, int posn, int cc)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_highlight_word(mText,line,posn,cc); textwidget_highlight_word(mText,line,posn,cc);
return; return;
} }
// underline the text at a given position and length in a given line // underline the text at a given position and length in a given line
void popup_report_underline_word(zdialog *zd, int line, int posn, int cc) void popup_report_underline_word(zdialog *zd, int line, int posn, int cc)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_underline_word(mText,line,posn,cc); textwidget_underline_word(mText,line,posn,cc);
return; return;
} }
// bold the text at a given position and length in a given line // bold the text at a given position and length in a given line
void popup_report_bold_word(zdialog *zd, int line, int posn, int cc) void popup_report_bold_word(zdialog *zd, int line, int posn, int cc)
{ {
if (! zdialog_valid(zd)) { Plog(0,"report cancelled \n"); return; } if (! zdialog_valid(zd)) { Plog(1,"report cancelled \n"); return; }
GtkWidget *mText = zdialog_gtkwidget(zd,"text"); GtkWidget *mText = zdialog_gtkwidget(zd,"text");
textwidget_bold_word(mText,line,posn,cc); textwidget_bold_word(mText,line,posn,cc);
return; return;
} }
// set font attributes for entire report // temp. kludge // set font attributes for entire report // temp. kludge
void popup_report_font_attributes(zdialog *zd) void popup_report_font_attributes(zdialog *zd)
{ {
if (! zdialog_valid(zd)) return; if (! zdialog_valid(zd)) return;
skipping to change at line 12714 skipping to change at line 12679
else isfull[nn] = 0; else isfull[nn] = 0;
if (isfull[nn] != reqfull[nn]) { // compensate GTK bug: FIXME if (isfull[nn] != reqfull[nn]) { // compensate GTK bug: FIXME
if (reqfull[nn]) gtk_window_fullscreen(GTK_WINDOW(window)); // the window fullscreens itself after if (reqfull[nn]) gtk_window_fullscreen(GTK_WINDOW(window)); // the window fullscreens itself after
else gtk_window_unfullscreen(GTK_WINDOW(window)); // being requested to unfullscreen else gtk_window_unfullscreen(GTK_WINDOW(window)); // being requested to unfullscreen
} }
return 1; return 1;
} }
/*******************************************************************************
*/
// popup a picklist at mouse position, return user choice
namespace popup_picklist_names
{
int menubusy;
cchar *menuchoice;
}
cchar * popup_picklist(GtkWidget *parent, cchar **list, cchar **desc, int Np)
// 22.35
{
using namespace popup_picklist_names;
void popup_picklist_func(GtkWidget *, cchar *menu);
GtkWidget *popmenu;
popmenu = create_popmenu();
if (desc) {
for (int ii = 0; ii < Np; ii++)
add_popmenu_item(popmenu,list[ii],popup_picklist_func,0,desc[ii]);
}
else {
for (int ii = 0; ii < Np; ii++)
add_popmenu_item(popmenu,list[ii],popup_picklist_func,0,0);
}
menubusy = 1;
menuchoice = 0;
popup_menu(parent,popmenu);
while (menubusy) zmainsleep(0.1);
g_object_ref_sink(popmenu);
return menuchoice;
}
void popup_picklist_func(GtkWidget *, cchar *menu)
{
using namespace popup_picklist_names;
menuchoice = menu;
menubusy = 0;
return;
}
/******************************************************************************* * /******************************************************************************* *
File chooser dialog for one or more files File chooser dialog for one or more files
Action: "file" select an existing file Action: "file" select an existing file
"files" select multiple existing files "files" select multiple existing files
"save" select an existing or new file "save" select an existing or new file
"folder" select existing folder "folder" select existing folder
"folders" select multiple existing folders "folders" select multiple existing folders
"create folder" select existing or new folder "create folder" select existing or new folder
skipping to change at line 13399 skipping to change at line 13412
pixbuf = gdk_pixbuf_new_from_file_at_size(file,128,128,&gerror); pixbuf = gdk_pixbuf_new_from_file_at_size(file,128,128,&gerror);
if (! pixbuf) { if (! pixbuf) {
if (gerror) Plog(0,"%s \n",gerror->message); if (gerror) Plog(0,"%s \n",gerror->message);
return; return;
} }
gtk_drag_set_icon_pixbuf(context,pixbuf,64,64); // hot spot is middle of image gtk_drag_set_icon_pixbuf(context,pixbuf,64,64); // hot spot is middle of image
return; return;
cancel: cancel:
Plog(1,"drag canceled \n"); Plog(2,"drag canceled \n");
return; return;
} }
// private function for "drag-data-get" signal // private function for "drag-data-get" signal
void drag_drop_source3(GtkWidget *widget, GdkDragContext *context, GtkSelectionD ata *data, int, int, void *ufunc) void drag_drop_source3(GtkWidget *widget, GdkDragContext *context, GtkSelectionD ata *data, int, int, void *ufunc)
{ {
drag_drop_source_func *ufunc2; drag_drop_source_func *ufunc2;
char *file = 0; char *file = 0;
// char *files[2] = { file, null }; // char *files[2] = { file, null };
ufunc2 = (drag_drop_source_func *) ufunc; ufunc2 = (drag_drop_source_func *) ufunc;
file = ufunc2(); file = ufunc2();
if (! file) goto cancel; if (! file) goto cancel;
gtk_selection_data_set_text(data,file,-1); // drops text gtk_selection_data_set_text(data,file,-1); // drops text
// gtk_selection_data_set_uris(data,files); // does nothing FIXME // gtk_selection_data_set_uris(data,files); // does nothing FIXME
return; return;
cancel: cancel:
Plog(1,"drag canceled \n"); Plog(2,"drag canceled \n");
return; return;
} }
// connect a user callback function to a drag-drop destination widget // connect a user callback function to a drag-drop destination widget
void drag_drop_dest(GtkWidget *widget, drag_drop_dest_func *ufunc) void drag_drop_dest(GtkWidget *widget, drag_drop_dest_func *ufunc)
{ {
int drag_drop_dest2(GtkWidget *, GdkDragContext *, int, int, void *, int, in t time, void *); int drag_drop_dest2(GtkWidget *, GdkDragContext *, int, int, void *, int, in t time, void *);
int drag_drop_dest3(GtkWidget *, void *, int, int, int, void *); int drag_drop_dest3(GtkWidget *, void *, int, int, int, void *);
int drag_drop_dest4(GtkWidget *, void *, int, void *); int drag_drop_dest4(GtkWidget *, void *, int, void *);
 End of changes. 68 change blocks. 
132 lines changed or deleted 144 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)