File: zfuncs.h

package info (click to toggle)
dkopp 8.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,052 kB
  • sloc: cpp: 12,545; makefile: 50
file content (710 lines) | stat: -rw-r--r-- 59,014 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
/********************************************************************************
   zfuncs.h      include file for zfuncs functions

   Copyright 2007-2024 Michael Cornelison
   source code URL: https://kornelix.net
   contact: mkornelix@gmail.com

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version. See https://www.gnu.org/licenses

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   See the GNU General Public License for more details.

*********************************************************************************/

#include <sys/sysinfo.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/file.h>
#include <sys/utsname.h>
#include <malloc.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <execinfo.h>
#include <locale.h>
#include <glob.h>
#include <gtk/gtk.h>

#define VERTICAL GTK_ORIENTATION_VERTICAL                                              //  GTK shortcuts
#define HORIZONTAL GTK_ORIENTATION_HORIZONTAL
#define PIXBUF GdkPixbuf
#define GDKCOLOR GdkColorspace

#define  int8    ch                                                                    //  number types
#define  int16   short
#define  int32   int
#define  int64   long long                                                             //  long long is always 64 bits
#define  uint8   unsigned char
#define  uint16  unsigned short
#define  uint32  unsigned int
#define  uint64  unsigned long long

#define  ch      char
#define  uch     unsigned char
#define  cch     const char

#define  VOL volatile

#define  STATB  struct stat                                                            //  stat() file status buffer

#define  mutex_t        pthread_mutex_t                                                //  abbreviations
#define  mutex_init     pthread_mutex_init
#define  mutex_lock     pthread_mutex_lock
#define  mutex_trylock  pthread_mutex_trylock
#define  mutex_unlock   pthread_mutex_unlock
#define  mutex_destroy  pthread_mutex_destroy

#define  XFCC 1000                                                                     //  max. file pathname cc tolerated
#define  null NULL
#define  true 1
#define  false 0
#define  NOP

//  trace execution: source file, function, line no, caller address

#define TRACE trace(__FILE__,__FUNCTION__,__LINE__,__builtin_return_address(0));

//  system functions ============================================================

void *zmalloc(int64 cc, ch *tag);                                                      //  malloc() wrapper
void zfree(void *pp);                                                                  //  free() wrapper
int  zmalloc_test(int64 cc);                                                           //  test if cc free memory available
double realmemory();                                                                   //  get available real memory in MB units
double availmemory();                                                                  //  get available memory (+swap) in MB units
ch * zstrdup(ch *zstring, ch *tag, int addcc = 0);                                     //  strdup() wrapper with added space
int  zstrcopy(ch *&zstring, ch *string, ch *tag, int addcc = 0);                       //  replace string with new string + added cc
void zmalloc_report(GtkWidget *parent);                                                //  memory usage by tag > popup report
void zmalloc_growth(GtkWidget *parent);                                                //  memory growth by tag > popup report
void xmessage(ch *message);                                                            //  popup message not needing GTK
void zexit(int popup, ch *message, ...);                                               //  exit a process and kill child processes
void zbacktrace();                                                                     //  produce a backtrace to stdout
void zappcrash(ch *format, ...);                                                       //  crash with popup message in text window
void catch_signals();                                                                  //  catch signals and do backtrace dump
void trace(ch *file, ch *func, int line, void *addr);                                  //  implements TRACE macro
void tracedump();                                                                      //  dump program trace data
ch * combine_argvs(int argc, ch *argv[], int Nth);                                     //  combine argv[ii] elements Nth to last
double get_seconds(int init = 0);                                                      //  get elapsed seconds since last call
void print_seconds(ch *label);                                                         //  print seconds since last call
double get_seconds(timespec *ts);                                                      //  real seconds from timespec struct
void start_timer(double &time0);                                                       //  start a timer
double get_timer(double &time0);                                                       //  get elapsed time in seconds
double CPUtime();                                                                      //  get elapsed process CPU time
int  memused();                                                                        //  get process real memory, MB
void compact_time(time_t DT, ch *compactDT);                                           //  time_t DT to yyyymmddhhmmss
void pretty_datetime(time_t DT, ch *prettyDT);                                         //  time_t DT to yyyy:mm:dd hh:mm:ss
void secs_datetime(double secs, int datetime[6]);                                      //  seconds to year/mon/day/hour/min/secs
void datetime_secs(int datetime[6], double *secs);                                     //  year/mon/day/hour/min/secs to seconds
int  parseprocfile(ch *pfile, ch *pname, double *value, ...);                          //  get data from /proc file
int  parseprocrec(ch *prec, int field, double *value, ...);                            //  get data from /proc file record
int  coretemp();                                                                       //  get CPU temperature (package temp)
int  disktemp(ch *disk);                                                               //  get disk temp, e.g. "/dev/sda"
void zsleep(double dsecs);                                                             //  sleep specified seconds
void zloop(double dsecs);                                                              //  loop specified seconds
void spinlock(int lock);                                                               //  lock/unlock enclosed code block
int  global_lock(ch *lockfile);                                                        //  obtain exclusive lock, multi-process
void global_unlock(int fd, ch *lockfile);                                              //  release the lock
int  resource_lock(int &resource);                                                     //  simple lock/unlock usable with GTK
void resource_unlock(int &resource);                                                   //  (never waits, returns lock status)
int  zget_locked(int &param);                                                          //  lock and get multi-thread parameter
void zput_locked(int &param, int value);                                               //  put and unlock multi-thread parameter
int  zadd_locked(int &param, int incr);                                                //  increment multi-thread parameter
pthread_t start_detached_thread(void * tfunc(void *), void * arg);                     //  start detached thread function
pthread_t start_Jthread(void * threadfunc(void *), void * arg);                        //  start joinable thread function
int  wait_Jthread(pthread_t tid);                                                      //  wait for completion (join thread)
void synch_threads(int NT = 0);                                                        //  synchronize NT threads
int  main_thread();                                                                    //  return 1 if main() thread, else 0
int  zshell(ch *options, ch *command, ...);                                            //  do shell command and get status
int  kill_procname(ch *wildname);                                                      //  kill processes matching wilcard name
int  signalProc(ch *pname, ch *signal);                                                //  send signal to process by process name
ch * fgets_trim(ch * buff, int bcc, FILE *, int bf = 0);                               //  fgets() + trim trailing \n \r (blanks)
ch * fgets_pend(ch * buff, int bcc, FILE *);                                           //  fgets() non-blocking wrapper
int  samefolder(ch *file1, ch *file2);                                                 //  returns 1 if files in same folder
int  parsefile(ch *path, ch *&folder, ch *&file, ch *&ext);                            //  parse components of a file name
void parsefile_free(ch *&folder, ch *&file, ch *&ext);                                 //  zfree file name components
int  renamez(ch *file1, ch *file2);                                                    //  rename, also across file systems
int  check_create_dir(ch *path);                                                       //  check if folder exists, ask to create
int  cp_copy(ch *sfile, ch *dfile);                                                    //  same, using shell "cp -f -p"
uint diskspace(ch *file);                                                              //  get disk space for given file, MB
ch * get_file_extension(ch *file);                                                     //  get correct .ext if file.ext is wrong
int  zreaddir(ch *folder, ch **&files);                                                //  return all files in a folder, sorted
int  zreadfile(ch *filename, ch **&rrecs);                                             //  read file, return array of records
int  zwritefile(ch *filename, ch **&rrecs);                                            //  write array of records to file
void zreadfile_free(ch **&rrecs);                                                      //  free zreadfile() memory

//  string functions ============================================================

int strmatch(cch *str1, cch *str2);                                                    //  true if strings equal, null strings allowed
int strmatchN(cch *str1, cch *str2, int cc);                                           //  true if leading N characters equal
int strmatchcase(cch *str1, cch *str2);                                                //  true if strings equal except for case
int strmatchcaseN(cch *str1, cch *str2, int cc);                                       //  true if leading N chars equal except case
ch * substringR(ch *string, ch *delims, int Nth);                                      //  get Nth delimited substring, thread-safe
ch * substringR(ch *string, ch delim, int Nth);                                        //  same, single delimiter
ch * substring(ch *string, ch *delims, int Nth);                                       //  same, no zfree() needed, not thread-safe
ch * substring(ch *string, ch delim, int Nth);                                         //  same, single delimiter
int  get_substrings(ch *instr, ch dlm, int cnt, int maxcc, ch **outstr);               //  get all substrings from delimited string
int  strHash(ch *string, uint max);                                                    //  string --> random int 0 to max-1
int  strncpy0(ch *dest, ch *source, uint cc);                                          //  strncpy, insure null, return 0 if fit
void strnPad(ch *dest, ch *source, int cc);                                            //  strncpy with blank padding to cc
int  strTrim(ch *dest, ch *source);                                                    //  remove trailing blanks
int  strTrim(ch *string);                                                              //  remove trailing blanks
int  strTrim2(ch *dest, ch *source);                                                   //  remove leading and trailing blanks
int  strTrim2(ch *string);                                                             //  remove leading and trailing blanks
int  strCompress(ch *dest, ch *source);                                                //  remove all blanks incl. embedded
int  strCompress(ch *string);                                                          //  remove all blanks
int  strncatv(ch *dest, int maxcc, ch *source, ...);                                   //  catenate strings (last = null)
int  strmatchV(ch *string, ...);                                                       //  compare to N strings, return 1-N or 0
void strToUpper(ch *dest, ch *source);                                                 //  move and conv. string to upper case
void strToUpper(ch *string);                                                           //  conv. string to upper case
void strToLower(ch *dest, ch *source);                                                 //  move and conv. string to lower case
void strToLower(ch *string);                                                           //  conv. string to lower case
int  repl_1str(ch *strin, ch *strout, int maxcc, ch *ssin, ch *ssout);                 //  copy string and replace 1 substring
int  repl_Nstrs(ch *strin, ch *strout, int maxcc, ...);                                //  copy string and replace N substrings
int  breakup_text(ch *in, ch **&out, ch *delims, int cc1, int cc2);                    //  break long string into substrings
void strncpyx(ch *out, ch *in, int ccin);                                              //  conv. string to hex format
void StripZeros(ch *pNum);                                                             //  1.230000E+12 --> 1.23E+12
int  blank_null(ch *string);                                                           //  test for blank/null string
int  clean_escapes(ch *string);                                                        //  replace \x escapes with real characters
int  utf8len(ch *utf8string);                                                          //  get graphic cc for UTF8 string
int  utf8substring(ch *utf8out, ch *utf8in, int pos, int cc);                          //  get graphic substring from UTF8 string
int  utf8_check(ch *string);                                                           //  check utf8 string for encoding errors
int  utf8_clean(ch *string);                                                           //  clean utf8 string: '?' > bad characters
int  utf8_position(ch *utf8in, int Nth);                                               //  get byte position of Nth graphic char.
int  zsed(ch *file, ...);                                                              //  replace string1/3/5... with string2/4/6...
ch * zstrstr(ch *haystack, ch *needle);                                                //  work like strstr() and strcasestr()
ch * zstrcasestr(ch *haystack, ch *needle);                                            //   (but "" does NOT match any string)
ch * zstrcpy(ch *dest, ch *source);                                                    //  strcpy with overlap allowed
ch * zstrncpy(ch *dest, ch *source, int cc);                                           //  strncpy with overlap allowed
int  zstrcmp(ch *s1, ch *s2);                                                          //  like strcmp, but \n terminates like null
int  zstrcmp2(ch *s1, ch *s2);                                                         //  strcmp using ch *args, not cch*
int  zstrcasecmp(ch *s1, ch *s2);                                                      //  strcasecmp using ch *args, not cch*
ch * zescape_quotes(ch *string);                                                       //  escape quotes for use in shell commands

//  number conversion ===========================================================

int convSI (ch *s, int &i, ch **delm = 0);                                             //  string to int
int convSI (ch *s, int &i, int low, int hi, ch **delm = 0);                            //  (with low/high limit checking)
int convSD (ch *s, double &d, ch **delm = 0);                                          //  string to double
int convSD (ch *s, double &d, double low, double hi, ch **delm = 0);                   //  (with low/high limit checking)
int convSF (ch *s, float &f, ch **delm = 0);                                           //  string to double
int convSF (ch *s, float &f, float low, float hi, ch **delm = 0);                      //  (with low/high limit checking)
int convIS (int iin, ch *outp, int *cc = 0);                                           //  int to string, returned cc
int convDS (double din, int prec, ch *outp, int *cc = 0);                              //  double to string, precision, output cc
double atofz(ch *string);                                                              //  atof() for comma/period decimal points
ch * formatKBMB(double fnum, int prec);                                                //  format nnn B, nn.n KB, n.nn MB, etc.

//  wildcard functions ==========================================================

int MatchWild(ch * wildstr, ch * str);                                                 //  wildcard string match (match = 0)
int MatchWildCase(ch * wildstr, ch * str);                                             //  wildcard string match, ignoring case
ch * SearchWild(ch *wpath, int &flag);                                                 //  wildcard file search
ch * SearchWildCase(ch *wpath, int &flag);                                             //  wildcard file search, ignoring case
int zfind(ch *pattern, ch **&flist, int &NF);                                          //  wildcard file search using glob()

//  search and sort functions ===================================================

int bsearch(int seekint, int nn, int list[]);                                          //  binary search sorted list[nn]
int bsearch(ch *seekrec, ch *allrecs, int recl, int nrecs);                            //  binary search sorted records
int bsearch(ch *seekrec, ch **allrecs, int N, int nrecs);                              //  binary search sorted pointers to recs

typedef int HeapSortUcomp(ch *rec1, ch *rec2);                                         //  return -1/0/+1 if rec1 </=/> rec2
//  single-thread versions
void heapsort(int vv[], int nn);                                                       //  Heap Sort - integer
void heapsort(float vv[], int nn);                                                     //  Heap Sort - float
void heapsort(double vv[], int nn);                                                    //  Heap Sort - double
void heapsort(ch *vv[], int nn, HeapSortUcomp);                                        //  Heap Sort - char *, user-defined order
//  4-thread versions
void HeapSort(int vv[], int nn);                                                       //  Heap Sort - integer
void HeapSort(float vv[], int nn);                                                     //  Heap Sort - float
void HeapSort(double vv[], int nn);                                                    //  Heap Sort - double
void HeapSort(ch *vv[], int nn);                                                       //  Heap Sort - char *, ascending order
void HeapSort(ch *vv1[], ch *vv2[], int nn);                                           //  Heap Sort - parallel char *, ascending
void HeapSort(ch *vv[], int nn, HeapSortUcomp);                                        //  Heap Sort - char *, user-defined order
void HeapSort(ch *recs, int RL, int NR, HeapSortUcomp);                                //  Heap Sort - records, user-defined order

int MemSort(ch * RECS, int RL, int NR, int KEYS[][3], int NK);                         //  memory sort, records with multiple keys

int zmember(int testval, int matchval1, ...);                                          //  test if value matches any in a list

//  hash table class ============================================================

class HashTab
{
   static int tries1;                                                                  //  insert tries
   static int tries2;                                                                  //  find/delete tries
   int     cap;                                                                        //  table capacity
   int     count;                                                                      //  strings contained
   int     cc;                                                                         //  string length
   ch      *table = 0;                                                                 //  table[cc][cap]
public:
   HashTab(int cc, int cap);                                                           //  constructor
   ~HashTab();                                                                         //  destructor
   int Add(ch * string);                                                               //  add a new string
   int Del(ch * string);                                                               //  delete a string
   int Find(ch * string);                                                              //  find a string
   int GetCount() { return count; };                                                   //  get string count
   int GetNext(int & first, ch * string);                                              //  get first/next string
   int Dump();                                                                         //  dump hash table
};

//  list processing functions ===================================================

typedef struct {                                                                       //  list data type
   int      count;                                                                     //  count of member strings
   ch       **mber = 0;                                                                //  member strings, null == missing
}  zlist_t;

zlist_t * zlist_new(int count);                                                        //  create zlist with 'count' empty members
void zlist_free(zlist_t *zlist);                                                       //  delete zlist, free memory
void zlist_dump(zlist_t *zlist);                                                       //  dump zlist to stdout
int zlist_count(zlist_t *zlist);                                                       //  get zlist member count
ch * zlist_get(zlist_t *zlist, int Nth);                                               //  get a zlist member
void zlist_put(zlist_t *zlist, ch *string, int Nth);                                   //  put a zlist member (replace existing)
void zlist_insert(zlist_t *zlist, ch *string, int Nth);                                //  insert Nth member, old Nth >> Nth+1
void zlist_remove(zlist_t *zlist, int Nth);                                            //  remove a zlist member (count -= 1)
void zlist_clear(zlist_t *zlist, int Nth);                                             //  clear zlist from Nth member to end
void zlist_purge(zlist_t *zlist);                                                      //  purge zlist of all null members
int zlist_add(zlist_t *zlist, ch *string, int Funiq);                                  //  add new member at first null or append
int zlist_append(zlist_t *zlist, ch *string, int Funiq);                               //  append new member at end (if unique)
int zlist_prepend(zlist_t *zlist, ch *string, int Funiq);                              //  prepend new member at posn 0 (if unique)
int zlist_find(zlist_t *zlist, ch *string, int posn);                                  //  find next match from posn
int zlist_findwild(zlist_t *zlist, ch *wstring, int posn);                             //  find next wildcard match from posn
zlist_t * zlist_copy(zlist_t *zlist1);                                                 //  copy a zlist
zlist_t * zlist_insert_zlist(zlist_t *zlist1, zlist_t *zlist2, int Nth);               //  insert zlist2 into zlist1 at posn Nth
zlist_t * zlist_remove(zlist_t *zlist1, zlist_t *zlist2);                              //  remove all members of zlist2 from zlist1
void zlist_sort(zlist_t *zlist);                                                       //  sort zlist ascending
void zlist_sort(zlist_t *zlist, int ccfunc(ch *, ch *));                               //  sort zlist via caller compare function
int zlist_to_file(zlist_t *zlist, ch *filename);                                       //  make file from zlist
zlist_t * zlist_from_file(ch *filename);                                               //  make zlist from file
zlist_t * zlist_from_folder(ch *foldername);                                           //  make zlist from files in a folder

//  random number functions =====================================================

int lrandz(int64 * seed);                                                              //  returns 0 to 0x7fffffff
int lrandz();                                                                          //  built-in seed
double drandz(int64 * seed);                                                           //  returns 0.0 to 0.99999...
double drandz();                                                                       //  built-in seed

//  spline curve-fitting functions ==============================================

void spline1(int nn, float *dx, float *dy);                                            //  define a curve using nn data points
float spline2(float x);                                                                //  return y-value for given x-value

//  FIFO queue for text strings, single or dual-thread access ===================

typedef struct  {
   int      qcap;                                                                      //  queue capacity
   int      qnewest;                                                                   //  newest entry position, circular
   int      qoldest;                                                                   //  oldest entry position, circular
   int      qdone;                                                                     //  flag, last entry added to queue
   ch       **qtext;                                                                   //  up to qcap text strings
}  Qtext;

void Qtext_open(Qtext *qtext, int cap);                                                //  initialize Qtext queue, empty
void Qtext_put(Qtext *qtext, ch *format, ...);                                         //  add text string to Qtext queue
ch * Qtext_get(Qtext *qtext);                                                          //  remove text string from Qtext queue
void Qtext_close(Qtext *qtext);                                                        //  close Qtext, zfree() leftover strings

//  compute variance for a list of numbers (std. deviation = sqrtf(variance))

float variance(float *vals, int N);

//  application initialization and administration ===============================

int zinitapp(ch *appvers, int argc, ch *argv[]);                                       //  initialize app (appname-N.N, custom homedir)

ch * get_zprefix();                                                                    //  get /usr or /usr/local  ...
ch * get_zhomedir();                                                                   //  get /home/user/.appname/
ch * get_zdatadir();                                                                   //  get data folder
ch * get_zimagedir();                                                                  //  get image folder
ch * get_zdocdir();                                                                    //  get document folder

void zabout(GtkWidget *parent);                                                        //  popup app 'about' information
void zsetfont(ch *newfont);                                                            //  set new app font and size
int  widget_font_metrics(GtkWidget *widget, int &fww, int &fhh);                       //  get widget font char width/height

int  get_zfilespec(ch *ftype, ch *fname, ch *filespec);                                //  get installation data file
void showz_logfile(GtkWidget *parent);                                                 //  show log file in popup window
void showz_textfile(ch *type, ch *file, GtkWidget *parent);                            //  show text file [.gz] in popup window
void showz_docfile(GtkWidget *, ch *docfile, ch *topic);                               //  show docfile topic and assoc. image


/********************************************************************************
   GTK utility functions
*********************************************************************************/

void zmainloop(int skip = 0);                                                          //  do main loop, process menu events
void zmainsleep(float secs);                                                           //  do main loop and sleep designated time


/********************************************************************************/

//  cairo drawing region for GDK window

typedef struct {
   GdkWindow               *win;
   cairo_rectangle_int_t   rect;
   cairo_region_t          *reg;
   GdkDrawingContext       *ctx;
   cairo_t                 *dcr = 0;
}  draw_context_t;

cairo_t * draw_context_create(GdkWindow *gdkwin, draw_context_t &context);
void draw_context_destroy(draw_context_t &context);


/********************************************************************************/

//  connect KB and mouse events to widget response function

#define G_SIGNAL(widget,event,func,arg) \
        g_signal_connect(G_OBJECT(widget),event,G_CALLBACK(func),(void *) arg)


/********************************************************************************/

//  txwidget functions - scrollable text widget for text reports and line editing
//  widget = zdialog_gtkwidget(zd,txwidget) where txwidget is a zdialog "text" widget type

void txwidget_clear(GtkWidget *widget);                                                //  clear all text
void txwidget_clear(GtkWidget *widget, int line);                                      //  clear text from line to end
int  txwidget_linecount(GtkWidget *widget);                                            //  get current line count
void txwidget_append(GtkWidget *widget, int bold, ch *format, ...);                    //  append line
void txwidget_append2(GtkWidget *widget, int bold, ch *format, ...);                   //  append line and scroll to end
void txwidget_insert(GtkWidget *widget, int bold, int line, ch *format, ...);          //  insert line
void txwidget_replace(GtkWidget *widget, int bold, int line, ch *format, ...);         //  replace line
void txwidget_delete(GtkWidget *widget, int line);                                     //  delete line
int  txwidget_find(GtkWidget *widget, ch *matchtext, int line1, int hilite);           //  find matching line
void txwidget_insert_pixbuf(GtkWidget *widget, int line, GdkPixbuf *pixbuf);           //  insert pixbuf image
void txwidget_scroll(GtkWidget *widget, int line);                                     //  scroll line on screen
void txwidget_scroll_top(GtkWidget *widget, int line);                                 //  scroll line to top of window
void txwidget_get_visible_lines(GtkWidget *widget, int &top, int &bott);               //  get range of visible lines
void txwidget_dump(GtkWidget *widget, ch *filename);                                   //  dump all text into a file
void txwidget_save(GtkWidget *widget, GtkWindow *parent);                              //  same, with save-as dialog
ch * txwidget_line(GtkWidget *widget, int line, int strip);                            //  retrieve line (strip \n)
void txwidget_highlight_line(GtkWidget *widget, int line);                             //  highlight line
ch * txwidget_word(GtkWidget *, int line, int posn, ch *dlims, ch &end);               //  retrieve word
void txwidget_highlight_word(GtkWidget *widget, int line, int posn, int cc);           //  highlight word
void txwidget_bold_word(GtkWidget *widget, int line, int posn, int cc);                //  make word bold
void txwidget_underline_word(GtkWidget *widget, int line, int posn, int cc);           //  make word underlined
void txwidget_font_attributes(GtkWidget *widget);                                      //  set font attributes for all text

typedef int txwidget_CBfunc_t(GtkWidget *, int line, int posn, ch *input);             //  widget event function to receive
void txwidget_set_eventfunc(GtkWidget *, txwidget_CBfunc_t func);                      //    mouse click and KB events


/********************************************************************************/

//  functions to simplify building menus, tool bars, status bars

typedef void cbFunc(GtkWidget *, ch *mname);                                           //  menu or button response function

GtkWidget * create_menubar(GtkWidget *vbox);                                           //  create menubar in packing box
GtkWidget * add_menubar_item(GtkWidget *mbar, ch *mname, cbFunc func = 0);             //  add menu item to menubar
GtkWidget * add_submenu_item(GtkWidget *mitem, ch *subname,                            //  add submenu item to menu item
                             cbFunc func = 0, ch *mtip = 0);                           //    with opt. function and popup tip

GtkWidget * create_toolbar(GtkWidget *vbox, int iconsize = 24);                        //  toolbar in packing box (no vert gtk3)
GtkWidget * add_toolbar_button(GtkWidget *tbar, ch *lab, ch *tip,                      //  add button with label, tool-tip, icon
                                 ch *icon, cbFunc func);

GtkWidget * create_stbar(GtkWidget *vbox);                                             //  create status bar in packing box
int stbar_message(GtkWidget *stbar, ch *message);                                      //  display message in status bar

/********************************************************************************/

GtkWidget * create_popmenu();                                                          //  create an empty popup menu
void add_popmenu(GtkWidget *popmenu, ch *item, cbFunc func, ch *arg, ch *tip);         //  add menu item to popup menu
void popup_menu(GtkWidget *, GtkWidget *popmenu);                                      //  pop-up menu at current mouse posn.

ch * popup_choose(zlist_t *zlist);                                                     //  popup to choose item from list
ch * popup_choose(ch *file);                                                           //  same, list from text file

/********************************************************************************/

//  create vertical menu/toolbar in vertical packing box

struct vmenuent {                                                                      //  menu data from caller
   ch          *name = 0;                                                              //  menu name, text
   ch          *icon = 0;                                                              //  opt. icon file name
   ch          *desc = 0;                                                              //  description (mouse hover popup)
   cbFunc      *LMfunc;                                                                //  menu func for left mouse click
   cbFunc      *RMfunc;                                                                //  menu func for right mouse click
   cbFunc      *setupfunc;                                                             //  opt. setup func for menu func
   ch          *arg = 0;                                                               //  callback arg for menu func
   ch          *setuparg = 0;                                                          //  callback arg for setup func
   ch          *RMarg = 0;                                                             //  callback arg for RMfunc
   PIXBUF      *pixbuf;                                                                //  icon pixbuf or null
   PangoLayout *playout1, *playout2;                                                   //  normal and bold menu text
   int         namex, namey;                                                           //  menu name position in layout
   int         iconx, icony;                                                           //  menu icon position
   int         ylo, yhi;                                                               //  menu height limits
   int         iconww, iconhh;                                                         //  icon width and height
};

struct Vmenu {
   GtkWidget   *vbox;                                                                  //  parent window (container)
   GtkWidget   *topwin;                                                                //  top-level window of parent
   GtkWidget   *layout;                                                                //  drawing window
   float       fgRGB[3];                                                               //  font color, RGB scaled 0-1
   float       bgRGB[3];                                                               //  background color, RGB scaled 0-1
   int         xmax, ymax;                                                             //  layout size
   int         mcount;                                                                 //  menu entry count
   vmenuent    menu[100];
};

Vmenu *Vmenu_new(GtkWidget *vbox, float fgRGB[3], float bgRGB[3]);                     //  create new menu in parent vbox
void Vmenu_add(Vmenu *vbm, ch *name, ch *icon, int iconww, int iconhh,                 //  add menu item with response function
                                       ch *desc, cbFunc func, ch *arg);                //  function may be popup_menu()
void Vmenu_add_setup(Vmenu *vbm, int me, cbFunc RMfunc, ch *arg);                      //  add opt. setup function
void Vmenu_add_RMfunc(Vmenu *vbm, int me, cbFunc RMfunc, ch *arg);                     //  add function for right mouse click
void Vmenu_block(int flag);                                                            //  block or unblock menu


/********************************************************************************/

//  spline curve edit functions

typedef void spcfunc_t(int spc);                                                       //  callback function, spline curve edit

struct spldat {                                                                        //  spline curve data
   GtkWidget   *drawarea;                                                              //  drawing area for spline curves
   spcfunc_t   *spcfunc;                                                               //  callback function when curve changed
   int         Nscale;                                                                 //  no. of fixed scale lines, 0-10
   float       xscale[2][10];                                                          //  2 x-values for end points
   float       yscale[2][10];                                                          //  2 y-values for end points
   int         Nspc;                                                                   //  number of curves, 1-10
   int         fact[10];                                                               //  curve is active
   int         vert[10];                                                               //  curve is vert. (1) or horz. (0)
   int         mod[10];                                                                //  curve is edited/modified
   int         nap[10];                                                                //  anchor points per curve
   float       apx[10][50], apy[10][50];                                               //  up to 50 anchor points per curve
   float       yval[10][1000];                                                         //  y-values for x = 0 to 1 by 0.001
};

spldat * splcurve_init(GtkWidget *frame, void func(int spc));                          //  initialize spline curves
int      splcurve_adjust(void *, GdkEventButton *event, spldat *);                     //  curve editing function
int      splcurve_addnode(spldat *, int spc, float px, float py);                      //  add a new node to a curve
int      splcurve_resize(GtkWidget *);                                                 //  adjust drawing area height
int      splcurve_draw(GtkWidget *, cairo_t *, spldat *);                              //  spline curve draw signal function
int      splcurve_generate(spldat *, int spc);                                         //  generate data from anchor points
float    splcurve_yval(spldat *, int spc, float xval);                                 //  get curve y-value
int      splcurve_load(spldat *sd, FILE *fid);                                         //  load curve from a file
int      splcurve_save(spldat *sd, FILE *fid);                                         //  save curve to a file


/********************************************************************************/

//   functions to implement GTK dialogs with less complexity
//   widget types: dialog, hbox, vbox, hsep, vsep, frame, scrwin, label, link,
//                 entry, edit, text, radio, check, button, togbutt, spin,
//                 combo, hscale, vscale, imagebutt, colorbutt, icon, image

#define zdmaxwidgets 300
#define zdmaxbutts 10
#define zdsentinel 0x97530000
#define zdialog_max 20

struct zwidget  {
      ch          *type = 0;                             //  hbox, vbox, label, entry ...
      ch          *wname = 0;                            //  widget name
      ch          *pname = 0;                            //  parent (container) name
      ch          *data = 0;                             //  widget data, initial / returned
      int         size;                                  //  text entry cc or image pixel size
      int         homog;                                 //  hbox/vbox: equal spacing flag
      int         expand;                                //  widget is expandable flag
      int         space;                                 //  extra padding space (pixels)
      int         wrap;                                  //  wrap mode for edit widget
      int         rescale;                               //  widget is rescaled for more resolution
      double      lval, nval, hval;                      //  scale range and neutral value
      double      lolim, hilim, step;                    //  range and step value for number widget
      zlist_t     *zlist;                                //  combo box list of text entries
      GtkWidget   *widget;                               //  GTK widget pointer
};

struct zdialog  {
      int         sentinel1;                             //  validity sentinel1
      int         uniqueID;                              //  unique ID, monotone increasing
      ch          *title = 0;                            //  dialog title
      void        *eventCB;                              //  dialog event user callback function
      void        *popup_report_CB;                      //  callback function for popup_report
      int         zrunning;                              //  dialog is running (0,1)
      int         zstat;                                 //  dialog status (from completion button)
      ch          zstat_button[40];                      //  completion button label
      int         disabled;                              //  widget signals/events are disabled
      int         saveposn;                              //  save and recall window position each use
      int         saveinputs;                            //  save and recall user inputs each use
      GtkWidget   *dialog;                               //  dialog window or null (box parent)
      GtkWidget   *parent;                               //  parent window or null
      ch          *ptype = 0;                            //  null or "window" or "box" parent
      ch          *compbutton[zdmaxbutts];               //  dialog completion button labels
      GtkWidget   *compwidget[zdmaxbutts];               //  dialog completion button widgets
      zwidget     widget[zdmaxwidgets];                  //  dialog widgets (EOF = type = 0)
      ch          event[40];                             //  active event or widget
      GtkWidget   *lastwidget;                           //  last widget active
      int         sentinel2;                             //  validity sentinel2
};

zdialog *zdialog_new(ch *title, GtkWidget *parent, ...);                               //  create a zdialog with opt. buttons
void zdialog_set_title(zdialog *zd, ch *title);                                        //  change zdialog title
void zdialog_set_modal(zdialog *zd);                                                   //  set zdialog modal
void zdialog_set_decorated(zdialog *zd, int decorated);                                //  set zdialog decorated or not
void zdialog_present(zdialog *zd);                                                     //  zdialog visible and on top
void zdialog_can_focus(zdialog *zd, int Fcan);                                         //  zdialog can/not have focus (e.g. report)
void zdialog_set_focus(zdialog *zd, ch *widget = null);                                //  set focus on window [ widget ]

int zdialog_add_widget_long(zdialog *zd,                                               //  add widget to zdialog
      ch *type, ch *wname, ch *pname,                                                  //  required args
      ch *data = 0, int size = 0, int homog = 0,                                       //  optional args
      int expand = 0, int space = 0, int wrap = 0);

int zdialog_add_widget(zdialog *zd,                                                    //  add widget to zdialog
      ch *type, ch *wname, ch *pname,                                                  //  (alternative form)
      ch *data = 0, ch *options = 0);                                                  //  "size=nn|homog|expand|space=nn|wrap"

int zdialog_valid(zdialog *zd, ch *title = 0);                                         //  return 1/0 if zdialog valid/invalid
int zdialog_valid2(zdialog *zd, ch *title = 0);                                        //  silent version of above
int zdialog_find_widget(zdialog *zd, ch *wname);                                       //  find zdialog widget from widget name
GtkWidget * zdialog_gtkwidget(zdialog *zd, ch *wname);                                 //  GTK widget from zdialog widget name
int zdialog_set_image(zdialog *zd, ch *wname, GdkPixbuf *);                            //  set "image" widget from a GDK pixbuf
int zdialog_add_ttip(zdialog *zd, ch *wname, ch *ttip);                                //  add popup tool tip to a widget
int zdialog_resize(zdialog *zd, int width, int height);                                //  set size > widget sizes
int zdialog_put_data(zdialog *zd, ch *wname, ch *data);                                //  put data in widget (entry, spin ...)
ch * zdialog_get_data(zdialog *zd, ch *wname);                                         //  get widget data
int zdialog_set_limits(zdialog *, ch *wname, double min, double max);                  //  set new widget limits (spin, scale)
int zdialog_get_limits(zdialog *, ch *wname, double &min, double &max);                //  get widget limits (spin, scale)
int zdialog_rescale(zdialog *zd, ch *wname, float, float, float);                      //  rescale widget, lo/neut/hi vals

typedef int zdialog_event(zdialog *zd, ch *wname);                                     //  widget event callback function
int zdialog_run(zdialog *zd, zdialog_event = 0, ch *posn = 0);                         //  run dialog, handle events
void KBevent(GdkEventKey *event);                                                      //  extern: pass KB events to main app

int zdialog_send_event(zdialog *zd, ch *event);                                        //  send an event to an active dialog
int zdialog_send_response(zdialog *zd, int zstat);                                     //  complete a dialog, set status
int zdialog_show(zdialog *zd, int flag);                                               //  show or hide a dialog
int zdialog_destroy(zdialog *zd);                                                      //  destroy dialog (caller resp.)
int zdialog_free(zdialog *&zd);                                                        //  free zdialog memory
int zdialog_wait(zdialog *zd);                                                         //  wait for dialog completion
int zdialog_goto(zdialog *zd, ch *wname);                                              //  put cursor at named widget
void zdialog_set_cursor(zdialog *zd, GdkCursor *cursor);                               //  set cursor for dialog window

int zdialog_stuff(zdialog *zd, ch *wname, ch *data);                                   //  stuff string data into widget
int zdialog_stuff(zdialog *zd, ch *wname, int  data);                                  //  stuff int data
int zdialog_stuff(zdialog *zd, ch *wname, double data);                                //  stuff double data
int zdialog_stuff(zdialog *zd, ch *wname, double data, ch *format);                    //  stuff double data, formatted
int zdialog_labelfont(zdialog *zd, ch *lab, ch *font, ch *txt);                        //  stuff label text with font

int zdialog_fetch(zdialog *zd, ch *wname, ch *data, int maxcc);                        //  get string data from widget
int zdialog_fetch(zdialog *zd, ch *wname, int  &data);                                 //  get int data
int zdialog_fetch(zdialog *zd, ch *wname, double &data);                               //  get double data
int zdialog_fetch(zdialog *zd, ch *wname, float &data);                                //  get float data

int zdialog_combo_clear(zdialog *zd, ch *wname);                                       //  clear combo box entries
int zdialog_combo_popup(zdialog *zd, ch *wname);                                       //  open combo box pick list

int zdialog_load_widgets(zdialog *zd, spldat *sd, ch *fname, FILE *fid);               //  load zdialog widgets from a file
int zdialog_save_widgets(zdialog *zd, spldat *sd, ch *fname, FILE *fid);               //  save zdialog widgets to a file
int zdialog_load_prev_widgets(zdialog *zd, spldat *sd, ch *fname);                     //  save last-used zdialog widgets
int zdialog_save_last_widgets(zdialog *zd, spldat *sd, ch *fname);                     //  load last-used zdialog widgets

int  zdialog_geometry(ch *action);                                                     //  load/save zdialog window positiion/size
void zdialog_set_position(zdialog *zd, ch *posn);                                      //  set initial/new zdialog window position
void zdialog_save_position(zdialog *zd);                                               //  save zdialog window position

int zdialog_inputs(ch *action);                                                        //  load or save zdialog input fields
int zdialog_save_inputs(zdialog *zd);                                                  //  save zdialog input fields when finished
int zdialog_load_inputs(zdialog *zd);                                                  //  restore zdialog inputs from prior use

ch * zdialog_text(GtkWidget *parent, ch *title, ch *inittext);                         //  get N text input lines from user
ch * zdialog_text1(GtkWidget *parent, ch *title, ch *inittext);                        //  get one text input line from user
ch * zdialog_password(GtkWidget *parent, ch *title, ch *inittext);                     //  same, but input is replaced with '*'s
int  zdialog_choose(GtkWidget *parent, ch *where, ch *message, ...);                   //  show message, return button choice
int  zdialog_edit_textfile(GtkWidget *parent, char *file);                             //  popup zdialog to edit a text file

//  write text report in popup window

zdialog * popup_report_open(ch *title, GtkWidget *parent, int ww, int hh,              //  open popup report - pixel size,
               int wrap, int Fheader, txwidget_CBfunc_t CBfunc, ...);                  //    wrap, header line, callback function
void popup_report_header(zdialog *zd, int bold, ch *format, ...);                      //  write non-scrolling header line
void popup_report_write(zdialog *zd, int bold, ch *format, ...);                       //  write text line
void popup_report_write2(zdialog *zd, int bold, ch *format, ...);                      //  write text line and scroll to end
void popup_report_top(zdialog *zd);                                                    //  go to top of report window
void popup_report_bottom(zdialog *zd);                                                 //  go to bottom of report window
void popup_report_clear(zdialog *zd);                                                  //  clear report window
void popup_report_clear(zdialog *zd, int line);                                        //  clear from line to end
void popup_report_insert(zdialog *zd, int bold, int line, ch *format, ...);            //  insert new line
void popup_report_replace(zdialog *zd, int bold, int line, ch *format, ...);           //  replace existing line
void popup_report_delete(zdialog *zd, int line);                                       //  delete line
int  popup_report_find(zdialog *zd, ch *matchtext, int line1);                         //  find matching line
void popup_report_insert_pixbuf(zdialog *zd, int line, GdkPixbuf *pixbuf);             //  insert pixbuf image after line
void popup_report_scroll(zdialog *zd, int line);                                       //  scroll to make line visible
void popup_report_scroll_top(zdialog *zd, int line);                                   //  scroll to put line at top
void popup_report_get_visible_lines(zdialog *zd, int &top, int &bott);                 //  get visible lines range
ch * popup_report_line(zdialog *zd, int line, int strip);                              //  retrieve line (strip \n)
ch * popup_report_word(zdialog *zd, int line, int posn, ch *dlims, ch &end);           //  retrieve word
void popup_report_highlight_line(zdialog *zd, int line);                               //  highlight line
void popup_report_highlight_word(zdialog *zd, int line, int posn, int cc);             //  highlight word
void popup_report_underline_word(zdialog *zd, int line, int posn, int cc);             //  underline word
void popup_report_bold_word(zdialog *zd, int line, int posn, int cc);                  //  bold word
void popup_report_font_attributes(zdialog *zd);                                        //  font attributes for entire report
void popup_report_close(zdialog *zd, int secs);                                        //  close window after seconds

int popup_command(ch *cmd, int ww=400, int hh=300, GtkWidget *p=0, int top=0);         //  shell command to popup window
int  monitor_file(ch *file);                                                           //  monitor a text file in a popup window

//  popups: message, dialog, image

ch * boldred(ch *message);                                                             //  convert dialog message to bold/red font
void zmessageACK_init();                                                               //  initz. for thread usage
void zmessageACK(GtkWidget *parent, ch *format, ... );                                 //  display message, wait for OK
int  zmessageYN(GtkWidget *parent, ch *format, ... );                                  //  display message, wait for YES/NO
zdialog * zmessage_post(GtkWidget *, ch *loc, int s, ch *f, ...);                      //  show message, timeout or cancel

void poptext_screen(ch *text, int px, int py, float s1, float s2);                     //  show popup text at screen posn
void poptext_mouse(ch *text, int dx, int dy, float s1, float s2);                      //  same, at mouse posn + offset
void poptext_widget(GtkWidget *, ch *tx, int x, int y, float s1, float s2);            //  same, at widget posn + offset
int  poptext_killnow();                                                                //  kill current popup window

//  file chooser dialogs for one file, multiple files, or folder

ch  * zgetfile(ch *title, GtkWindow *parent, ch *action, ch *file, int hidden = 0);
ch ** zgetfiles(ch *title, GtkWindow *parent, ch *action, ch *file, int hidden = 0);
ch  * zgetfolder(ch *title, GtkWindow *parent, ch *initfolder);

//  print an image file, choosing printer, paper, orientation, margins, and scale

void print_image_file(GtkWidget *parent, ch *imagefile);

//  drag and drop functions

typedef ch * drag_drop_source_func();                                                  //  user function, set drag-drop text
typedef void drag_drop_dest_func(int x, int y, ch *text);                              //  user function, get drag-drop text
void drag_drop_source(GtkWidget *window, drag_drop_source_func);                       //  connect source window to user function
void drag_drop_dest(GtkWidget *window, drag_drop_dest_func);                           //  connect dest. window to user function

//  miscellaneous GDK/GTK functions

PIXBUF * get_thumbnail(ch *fpath, int size);                                           //  get sized thumbnail for image file
GdkCursor * zmakecursor(ch *iconfile);                                                 //  make a cursor from an image file
PIXBUF * gdk_pixbuf_stripalpha(PIXBUF *pixbuf);                                        //  strip alpha channel from pixbuf
PIXBUF * text_pixbuf(ch *text, ch *font, int fsize, GtkWidget *);                      //  create pixbuf with text using font

int  move_pointer(GtkWidget *, int px, int py);                                        //  move the mouse pointer to px, py
void window_to_mouse(GtkWidget *window);                                               //  move GtkWidget/window to mouse position