home *** CD-ROM | disk | FTP | other *** search
/ Vectronix 2 / VECTRONIX2.iso / FILES_01 / GENEVANO.LZH / GEVA_NEO.MSA / TASKMAN.C < prev    next >
Text File  |  1993-06-17  |  48KB  |  1,632 lines

  1. /*                     The MAGIC Task Manager
  2.                             by Dan Wilga
  3.                 Copyright ╜ 1993, Gribnif Software
  4.                         All rights reserved.
  5.  
  6.  This source code is provided to registered owners of MAGIC as a learning
  7.  tool. No portion of this code can be sold or used for commercial purposes
  8.  without the permission of Gribnif Software. Modified versions of the Task
  9.  Manager may not be distributed.
  10.  
  11.  This file is only partly commented so far
  12. */
  13.  
  14. #include "aes.h"
  15. #include "vdi.h"
  16. #include "new_aes.h"            /* AES 4.0 extensions */
  17. #include "xwind.h"              /* MAGIC extensions */
  18. #include "tos.h"
  19. #include "string.h"
  20. #include "stdio.h"
  21. #include "stdlib.h"
  22. #include "taskman.h"            /* resource file constants */
  23.  
  24. /* window type for the main window */
  25. #define WIN_TYPE FULLER|NAME|MOVER|SIZER|X_MENU|CLOSER|UPARROW|DNARROW|VSLIDE
  26.  
  27. /* definitions for seeing if MAGIC is present, by way of JARxxx */
  28. #define CJar_cookie     0x434A6172L     /* "CJar" */
  29. #define my_cookie       0x4D414743      /* "MAGC" */
  30. #define _VDO_COOKIE     0x5F56444FL     /* _VDO */
  31. #define CJar_xbios      0x434A          /* "CJ" */
  32. #define CJar_OK         0x6172          /* "ar" */
  33. #define CJar(mode,cookie,value)         (int)xbios(CJar_xbios,mode,cookie,value)
  34.  
  35. /* root window object */
  36. OBJECT blank[65] = { -1, -1, -1, G_BOX, TOUCHEXIT, 0, 0x1070L };
  37. /* new item in the Tasks list */
  38. OBJECT new[] = { -1, -1, -1, G_STRING, SELECTABLE|TOUCHEXIT|RBUTTON, X_MAGIC, 0L, 0, 0, 0x060A, 1 };
  39. /* window dimensions, inside and outside */
  40. GRECT winner, max, wsize = { 50, 60, 250, 100 };
  41.  
  42. /* hold info for up to 65 applications */
  43. struct App
  44. {
  45.   char name[12];
  46.   int num, asleep;
  47. } app[65];
  48.  
  49. int apid,       /* my application ID */
  50.     apps,       /* number of apps in use */
  51.     char_h,     /* height of a char in G_STRING */
  52.     tasknum,    /* index of currently selected task (0=none) */
  53.     flagmode,   /* 0 for global flag editing */
  54.     flagnum,    /* index or apid of flag being edited */
  55.     fknum,      /* number (0-4) of flag key being edited */
  56.     dattnum,    /* */
  57.     color_mode;    /* 0 = 1-plane, 1 = 2-plane, 2 = 4-plane, 3 = 8+ plane */
  58.     
  59. char **new_flag,/* points to the string "--New--" within the RSC file */
  60.      **sys_font,/* points to the string "System" within the RSC file */
  61.      was_new;   /* != 0 if the user used the New button in flag editor */
  62.  
  63. SETTINGS set0,  /* MAGIC settings when dialog got opened (for Cancel) */
  64.          set;   /* current settings */
  65.  
  66. APPFLAGS apf0,  /* flags when dialog got opened */
  67.          apf;   /* current flags */
  68.  
  69. OBJECT *menu,       /* points to the main window menu tree */
  70.        *colors,        /* points to the colors popup menu */
  71.        *patterns,    /* points to the patterns popup menu */
  72.        *fontpop;    /* points to the fonts popup menu */
  73.  
  74. #define MENU_START  -5
  75. #define APP_SWITCH  -4
  76. #define APP_SLEEP   -3
  77. #define ASCII_TABLE -2
  78. #define REDRAW_ALL  -1
  79. int xkey=MENU_START;    /* index of key being edited in the Keyboard dialog */
  80.  
  81. int vdi_hand,        /* VDI device handle */
  82.     work_in[] = { 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, 2 },
  83.     work_out[57],    /* returns from v_opnvwk() */
  84.     has_gdos,        /* indicates presence of GDOS */
  85.     fonts,        /* number of fonts available */
  86.     font_id[16],    /* ID's of up to 16 fonts */
  87.     font_wid,        /* width of one char in the current font */
  88.     font_ht,        /* height of one char in the current font */
  89.     font_num;        /* index of the current font */
  90.  
  91. char *mover_text,    /* points to text in mover of Window options */
  92.      *info_text;    /* points to text in info bar in Window opts */
  93.  
  94. XFONTINFO fontinfo,        /* info about the font used by MAGIC */
  95.           fontinfo0;    /* initial state of fontinfo */
  96.  
  97. /* some function prototypes */
  98. void set_if( OBJECT *tree, int num, int true );
  99. void start_form( int fnum, int tnum, int type );
  100. void k_mode( OBJECT *o, int fnum, int mode, int draw );
  101. void k_set( OBJECT *o, int is_main, int draw );
  102. void close_vdi(void);
  103. int mo_init( OBJECT *o );
  104. int k_init( OBJECT *o );
  105. int wo_init( OBJECT *o );
  106. int d_init( OBJECT *o );
  107. int vo_init( OBJECT *o );
  108. int fo_init( OBJECT *o );
  109. int fk_init( OBJECT *o );
  110. int mo_touch( OBJECT *o, int num );
  111. int k_touch( OBJECT *o, int num );
  112. int fo_touch( OBJECT *o, int num );
  113. int fk_touch( OBJECT *o, int num );
  114. int d_touch( OBJECT *o, int num );
  115. int wo_touch( OBJECT *o, int num );
  116. int mo_exit( OBJECT *o, int num );
  117. int fo_exit( OBJECT *o, int num );
  118. int k_exit( OBJECT *o, int num );
  119. int wo_exit( OBJECT *o, int num );
  120. int d_exit( OBJECT *o, int num );
  121. int vo_exit( OBJECT *o, int num );
  122.  
  123. /* describe a modeless dialog */
  124. typedef struct
  125. {
  126.   int handle;                           /* handle of window containing dial */
  127.   OBJECT *tree;                         /* dial's object tree */
  128.   int (*init)( OBJECT *o );             /* function to initialize it */
  129.   int (*touch)( OBJECT *o, int num );   /* called when TOUCHEXIT is clicked */
  130.   int (*exit)( OBJECT *o, int num );    /* called when EXIT is clicked */
  131. } FORM;
  132.  
  133. FORM form[] = { { 0, 0L, k_init, k_touch, k_exit },     /* Keyboard */
  134.                 { 0, 0L, mo_init, mo_touch, mo_exit },  /* Misc Options */
  135.                 { 0, 0L, d_init, d_touch, d_exit },     /* Dialog Options */
  136.                 { 0, 0L, wo_init, wo_touch, wo_exit },  /* Window Options */
  137.                 { 0, 0L, vo_init, 0L, vo_exit },        /* Video */
  138.                 { 0, 0L, fo_init, fo_touch, fo_exit },  /* Flags */
  139.                 { 0, 0L, fk_init, fk_touch, k_exit },   /* Flag Keys */
  140.                 { 0, 0L, 0L } };                        /* end of list */
  141.  
  142. /***
  143. /* Convert from a TEDINFO (te_ptext) filename to a regular string */
  144. void from_edit( char *src, char *dest )
  145. {
  146.   int i=0;
  147.   
  148.   do
  149.   {
  150.     if( *src != ' ' ) *dest++ = *src;
  151.     if( i++==7 && *(src+1) && *(src+1)!=' ' ) *dest++ = '.';
  152.   }
  153.   while( *src++ && i<11 );
  154.   if( i==11 ) *dest++ = '\0';
  155. }
  156.  
  157. /* Convert from a regular string to a TEDINFO (te_ptext) filename */
  158. void to_edit( char *src, char *dest )
  159. {
  160.   int j=0;
  161.   
  162.   while( *src && j<12 )
  163.   {
  164.     if( *src != '.' || j>7 )
  165.     {
  166.       if( *src == '.' ) src++;
  167.       else if( *src!=' ' ) *dest++ = *src++;    /* elim spaces */
  168.     }
  169.     else *dest++ = ' ';
  170.     j++;
  171.   }
  172.   *dest = 0;
  173. } ***/
  174.  
  175. int alert( int num )
  176. {
  177.   char **ptr;
  178.   
  179.   rsrc_gaddr( 15, num, &ptr );
  180.   return form_alert( 1, *ptr );
  181. }
  182.  
  183. /* Close and delete a window */
  184. void close_wind( int *hand )
  185. {
  186.   if( *hand )
  187.   {
  188.     if( *hand==form[3].handle ) close_vdi();
  189.     wind_close(*hand);
  190.     wind_delete(*hand);
  191.     *hand=0;
  192.   }
  193. }
  194.  
  195. /* Get MAGIC's current settings */
  196. void get_set(void)
  197. {
  198.   x_settings( 0, sizeof(SETTINGS), &set0 );
  199.   x_settings( 0, sizeof(SETTINGS), &set );
  200. }
  201.  
  202. /* initialize Misc Options dialog */
  203. int mo_init( OBJECT *o )
  204. {
  205.   get_set();
  206.   set_if( o, MOPULL, set.flags.s.pulldown );
  207.   set_if( o, MOINS, set.flags.s.insert_mode );
  208.   set_if( o, MOFOLL, set.flags.s.alerts_under_mouse );
  209.   set_if( o, MOCOL, set.flags.s.fsel_1col );
  210.   set_if( o, MOLONG, set.flags.s.long_titles );
  211.   set_if( o, MOGROW, set.flags.s.grow_shrink );
  212.   set_if( o, MOTOP, set.flags.s.tear_aways_topped );
  213.   x_sprintf( o[MOGAD].ob_spec.tedinfo->te_ptext, "%d", set.gadget_pause*20 );
  214.   return 1;
  215. }
  216.  
  217. /* Misc Options touchexit event */
  218. int mo_touch( OBJECT *o, int num )
  219. {
  220.   num++;                /* object clicked on, not used here */
  221.   /* get all settings from the dialog */
  222.   set.flags.s.pulldown = o[MOPULL].ob_state&SELECTED;
  223.   set.flags.s.insert_mode = o[MOINS].ob_state&SELECTED;
  224.   set.flags.s.alerts_under_mouse = o[MOFOLL].ob_state&SELECTED;
  225.   set.flags.s.fsel_1col = o[MOCOL].ob_state&SELECTED;
  226.   set.flags.s.long_titles = o[MOLONG].ob_state&SELECTED;
  227.   set.flags.s.grow_shrink = o[MOGROW].ob_state&SELECTED;
  228.   set.flags.s.tear_aways_topped = o[MOTOP].ob_state&SELECTED;
  229.   set.gadget_pause = atoi(o[MOGAD].ob_spec.tedinfo->te_ptext)/20;
  230.   /* set them in MAGIC */
  231.   x_settings( 1, sizeof(SETTINGS), &set );
  232.   return -1;
  233. }
  234.  
  235. /* Misc Options exit event */
  236. int mo_exit( OBJECT *o, int num )
  237. {
  238.   if( num!=MOOK ) x_settings( 1, sizeof(SETTINGS), &set0 );     /* Cancel */
  239.   else mo_touch( o, 0 );        /* get settings and set in MAGIC */
  240.   return 1;                     /* close dialog */
  241. }
  242.  
  243. /* hide or show an object */
  244. void hide_if( OBJECT *o, int num, int truth )
  245. {
  246.   if( !truth ) o[num].ob_flags |= HIDETREE;
  247.   else o[num].ob_flags &= ~HIDETREE;
  248. }
  249.  
  250. /* set an object to be editable or not editable */
  251. void edit_if( OBJECT *o, int num, int truth )
  252. {
  253.   if( !truth ) o[num].ob_flags &= ~EDITABLE;
  254.   else o[num].ob_flags |= EDITABLE;
  255. }
  256.  
  257. /* get current flags from dialog */
  258. void fo_stat( OBJECT *o )
  259. {
  260.   x_appl_flags( flagmode, flagnum, &apf0 );
  261.   apf = apf0;
  262.   x_form_filename( o, FONAME, 0, flagmode ? app[tasknum-1].name+2 : apf.name );
  263.   edit_if( o, FONAME, !flagmode && flagnum );
  264.   hide_if( o, FONAME, flagmode || flagnum );
  265.   hide_if( o, FOPREV, !flagmode && flagnum );
  266.   o[FODESC].ob_spec.tedinfo->te_ptext = apf.desc;
  267.   edit_if( o, FODESC, !flagmode && flagnum );
  268.   hide_if( o, FONEXT, !flagmode && x_appl_flags( 0, flagnum+1, 0L ) );
  269.   set_if( o, FOSPEC, apf.flags.s.special_types );
  270.   set_if( o, FOLIMIT, apf.flags.s.limit_memory );
  271.   set_if( o, FOKEEP, apf.flags.s.keep_deskmenu );
  272.   set_if( o, FOAES40, apf.flags.s.AES40_msgs );
  273.   set_if( o, FOREDRAW, apf.flags.s.exit_redraw );
  274.   x_sprintf( o[FOLNUM].ob_spec.tedinfo->te_ptext, "%d",
  275.       apf.flags.s.mem_limit );
  276.   set_if( o, FOMULTI, apf.flags.s.multitask );
  277.   hide_if( o, FOMULTI, !flagmode );
  278.   set_if( o, FOHAND, apf.flags.s.limit_handles );
  279.   hide_if( o, FOHAND, !flagmode );
  280.   set_if( o, FOLEFT, apf.flags.s.off_left );
  281.   set_if( o, FOROUND, apf.flags.s.round_buttons );
  282.   set_if( o, FOAUTO, apf.flags.s.kbd_equivs );
  283.   set_if( o, FOUNDRAW, apf.flags.s.undo_equivs );
  284.   hide_if( o, FODEL, !flagmode && flagnum );
  285.   hide_if( o, FONEW, !flagmode );
  286.   if( form[5].handle>0 ) wind_set( form[5].handle, X_WF_DIALOG, form[5].tree );
  287.   if( form[6].handle>0 ) k_set( form[6].tree, 0, 1 );
  288. }
  289.  
  290. int fo_init( OBJECT *o )
  291. {
  292.   flagmode = tasknum>0 ? 3 : 0;
  293.   flagnum = tasknum>0 ? app[tasknum-1].num : 0;
  294.   fo_stat(o);
  295.   was_new = 0;
  296.   return 1;
  297. }
  298.  
  299. int fo_set( OBJECT *o, int warn )
  300. {
  301.   x_form_filename( o, FONAME, 1, apf.name );
  302.   if( flagmode || !flagnum || apf.name[0] && strncmp(apf.name,*new_flag,12) )
  303.   {
  304.     apf.flags.s.special_types = o[FOSPEC].ob_state&SELECTED;
  305.     apf.flags.s.limit_memory = o[FOLIMIT].ob_state&SELECTED;
  306.     apf.flags.s.exit_redraw = o[FOREDRAW].ob_state&SELECTED;
  307.     apf.flags.s.keep_deskmenu = o[FOKEEP].ob_state&SELECTED;
  308.     apf.flags.s.AES40_msgs = o[FOAES40].ob_state&SELECTED;
  309.     apf.flags.s.mem_limit = atoi( o[FOLNUM].ob_spec.tedinfo->te_ptext );
  310.     apf.flags.s.multitask = o[FOMULTI].ob_state&SELECTED;
  311.     apf.flags.s.limit_handles = o[FOHAND].ob_state&SELECTED;
  312.     apf.flags.s.off_left = o[FOLEFT].ob_state&SELECTED;
  313.     apf.flags.s.round_buttons = o[FOROUND].ob_state&SELECTED;
  314.     apf.flags.s.kbd_equivs = o[FOAUTO].ob_state&SELECTED;
  315.     apf.flags.s.undo_equivs = o[FOUNDRAW].ob_state&SELECTED;
  316.     x_appl_flags( flagmode+1, flagnum, &apf );
  317.     return 1;
  318.   }
  319.   else
  320.   {
  321.     if( warn ) alert( ALNONAME );
  322.     return 0;
  323.   }
  324. }
  325.  
  326. int fo_touch( OBJECT *o, int num )
  327. {
  328.   if( num==FOPREV )
  329.   {
  330.     if( flagnum && fo_set( o, 1 ) )
  331.     {
  332.       flagnum--;
  333.       fo_stat(o);
  334.       was_new = 0;
  335.     }
  336.   }
  337.   else if( num==FONEXT )
  338.   {
  339.     if( x_appl_flags( flagmode, flagnum+1, 0L ) && fo_set( o, 1 ) )
  340.     {
  341.       flagnum++;
  342.       fo_stat(o);
  343.       was_new = 0;
  344.     }
  345.   }
  346.   else fo_set( o, 0 );
  347.   return -1;
  348. }
  349.  
  350. int fo_exit( OBJECT *o, int num )
  351. {
  352.   switch(num)
  353.   {
  354.     case FODEL:
  355.       x_appl_flags( 2, flagnum, 0L );
  356.       flagnum--;
  357.       fo_stat(o);
  358.       was_new = 0;
  359.       return 0;
  360.     case FONEW:
  361.       if( fo_set( o, 1 ) )
  362.       {
  363.         x_appl_flags( 0, 0, &apf );     /* get default */
  364.         strcpy( apf.name, *new_flag );  /* set name to "--New--" */
  365.         apf.desc[0] = 0;
  366.         x_appl_flags( 1, -1, &apf );    /* create new */
  367.         while( x_appl_flags( 0, flagnum+1, &apf ) ) flagnum++;  /* find end */
  368.         apf0 = apf;
  369.         fo_stat(o);
  370.         was_new = 1;
  371.       }
  372.       return 0;
  373.     case FOKEYS:
  374.       if( !fo_set( o, 1 ) ) return 0;
  375.       start_form( 6, FLKEYS, NAME|MOVER );
  376.       return 0;
  377.     case FOOK:
  378.       if( !fo_set( o, 1 ) ) return 0;
  379.       break;
  380.     default:
  381.       if( !was_new ) x_appl_flags( flagmode+1, flagnum, &apf0 );
  382.       else x_appl_flags( 2, flagnum, 0L );      /* delete it */
  383.   }
  384.   /* exiting, so close the Keys dialog */
  385.   if( form[6].handle>0 ) close_wind(&form[6].handle);
  386.   return 1;
  387. }
  388.  
  389. int fk_init( OBJECT *o )
  390. {
  391.   int i;
  392.   
  393.   if( !flagmode && !flagnum ) fknum = 1;
  394.   else fknum = 0;
  395.   for( i=0; i<5; i++ )
  396.     set_if( o, i+KOMENU, i==fknum );
  397.   k_mode( o, 6, 0, 0 );
  398.   k_set( o, 0, 0 );
  399.   return 1;
  400. }
  401.  
  402. int k_init( OBJECT *o )
  403. {
  404.   WIND_TREE wt;
  405.   int hand = form[0].handle;
  406.  
  407.   k_mode( o, 0, 0, 0 );
  408.   get_set();
  409.   k_set( o, 1, 0 );
  410.   wind_set( hand, WF_HSLIDE, 500 );
  411.   wind_set( hand, WF_HSLSIZE, 0 );
  412.   wind_set( hand, WF_VSLIDE, 500 );
  413.   wind_set( hand, WF_VSLSIZE, 0 );
  414.   wt.handle = hand;
  415.   x_wind_tree( X_WT_GETCNT, &wt );
  416.   wt.count = -1;
  417.   wt.flag &= ~(X_WTFL_SLIDERS|X_WTFL_CLICKS);
  418.   x_wind_tree( X_WT_SET, &wt );
  419.   return 1;
  420. }
  421.  
  422. void ksel( int num, int flag )
  423. {
  424.   num = num-MENU_START+KOMENU;
  425.   if( flag ) form[0].tree[num].ob_state |= SELECTED;
  426.   else form[0].tree[num].ob_state &= ~SELECTED;
  427.   x_wdial_draw( form[0].handle, num, 0 );
  428. }
  429.  
  430. void new_key( int num, int convert )
  431. {
  432.   static int keyx[] = { XS_CLOSE, 99, XS_CYCLE, XS_FULL, XS_LFINFO, 99, XS_RTINFO };
  433.  
  434.   if( convert )
  435.   {
  436.     if( --num > sizeof(keyx)/sizeof(int) ) return;
  437.     num = keyx[num];
  438.   }
  439.   if( num!=99 && num!=xkey )
  440.   {
  441.     if( xkey<0 && num>=0 ) ksel( xkey, 0 );
  442.     xkey = num;
  443.     k_set( form[0].tree, 1, 1 );
  444.   }
  445. }
  446.  
  447. unsigned char k_shift( OBJECT *o )
  448. {
  449.   return ((o[KOALT].ob_state&SELECTED)<<3) |
  450.          ((o[KOCNTRL].ob_state&SELECTED)<<2) |
  451.          ((o[KOSHIFT].ob_state&SELECTED) ? 3 : 0);
  452. }
  453.  
  454. int fk_touch( OBJECT *o, int num )
  455. {
  456.   if( num<KOMENU || num>KOREDRAW )
  457.   {
  458.     (&apf.open_key+fknum)->shift = k_shift(o);
  459.     fo_set( form[5].tree, 1 );
  460.   }
  461.   else if( fknum != num-KOMENU && !(o[num].ob_state&DISABLED) )
  462.   {
  463.     fknum = num-KOMENU;
  464.     k_set( o, 0, 1 );
  465.   }
  466.   return -1;
  467. }
  468.  
  469. int k_touch( OBJECT *o, int num )
  470. {
  471.   if( num<KOMENU || num>KOREDRAW )
  472.   {
  473.     set.wind_keys[xkey].shift = k_shift(o);
  474.     x_settings( 1, sizeof(SETTINGS), &set );
  475.   }
  476.   else new_key( num-KOMENU+MENU_START, 0 );
  477.   return -1;
  478. }
  479.  
  480. int k_exit( OBJECT *o, int num )
  481. {
  482.   int sh=0, key=0, dum, is_main;
  483.   KEYCODE *k;
  484.   
  485.   is_main = o == form[0].tree;
  486.   switch( num )
  487.   {
  488.     case KOQUIT:
  489.       return 1;
  490.     case KOREAD:
  491.       k_mode( o, is_main?0:6, 1, 1 );
  492.       wind_update( BEG_UPDATE );
  493.       evnt_multi( MU_KEYBD,  0,0,0,  0,0,0,0,0,
  494.           0,0,0,0,0,  &dum,  0,0,  &dum, &dum, &dum, &sh, &key, &dum );
  495.       wind_update( END_UPDATE );
  496.       k_mode( o, is_main?0:6, 0, 1 );
  497.       if( sh&3 ) sh |= 3;
  498.       /* fall through to process key */
  499.     case KOCLEAR:    /* key=sh=0 for clear */
  500.       k = is_main ? &set.wind_keys[xkey] : &apf.open_key+fknum;
  501.       k->shift = sh&0xf;
  502.       k->scan = key>>8;
  503.       k->ascii = 0;
  504.       k_set( o, is_main, 1 );
  505.       if( is_main ) x_settings( 1, sizeof(SETTINGS), &set );
  506.       else fo_set( form[5].tree, 1 );
  507.       return 0;
  508.     default:
  509.       if( is_main ) x_settings( 1, sizeof(SETTINGS), &set0 );
  510.       return 0;
  511.   }
  512. }
  513.  
  514. char reztbl[] = { 0, 1, 2, 7, 4, 6 };
  515.  
  516. int vo_exit( OBJECT *o, int num )
  517. {
  518.   int rez, i;
  519.   
  520.   if( num==VOOK )
  521.     for( i=VOSTLOW; i<=VOSTLOW+5; i++ )
  522.       if( o[i].ob_state & SELECTED )
  523.         if( (rez = reztbl[i-VOSTLOW]) != Getrez() )
  524.             shel_write( 5, rez+2, 0, 0L, 0L );
  525.   return 1;
  526. }
  527.  
  528. int vo_init( OBJECT *o )
  529. {
  530.   int rez, i;
  531.   long vid;
  532.   char TT_vid;
  533.   
  534.   rez = Getrez();
  535.   TT_vid = CJar( 0, _VDO_COOKIE, &vid ) == CJar_OK && (int)(vid>>16)==2;
  536.   for( i=VOSTLOW; i<=VOSTLOW+5; i++ )
  537.     if( rez==8 && i!=VOSTLOW+5 || TT_vid && i==VOSTLOW+5 ||
  538.         !TT_vid && rez==2 && i!=VOSTLOW+2 ||
  539.         !TT_vid && rez!=2 && i==VOSTLOW+2 ||
  540.         !TT_vid && i>VOSTLOW+2 )
  541.     {
  542.       o[i].ob_state |= DISABLED;
  543.       o[i].ob_state &= ~SELECTED;
  544.     }
  545.     else
  546.     {
  547.       o[i].ob_state &= ~DISABLED;
  548.       if( reztbl[i-VOSTLOW]==rez ) o[i].ob_state |= SELECTED;
  549.       else o[i].ob_state &= ~SELECTED;
  550.     }
  551.   return 1;
  552. }
  553.  
  554. void k_mode( OBJECT *o, int fnum, int mode, int draw )
  555. {
  556.   hide_if( o, KOCLICK, !mode );
  557.   hide_if( o, KOPRESS, mode );
  558.   if( draw ) x_wdial_draw( form[fnum].handle, KOBACK, 8 );
  559. }
  560.  
  561. void k_set( OBJECT *o, int is_main, int draw )
  562. {
  563.   int i;
  564.   unsigned char *ptr, c, c2;
  565.   char **p;
  566.   KEYCODE *key;
  567.   static unsigned char 
  568.       keycode[] = { 0, 1, 0xf, 0xe, 0x53, 0x52, 0x62, 0x61, 0x47, 0x48, 0x50,
  569.           0x4d, 0x4b, 0x72, 0x60, 0x39 },
  570.       keynam[][6] = { "???", "Esc", "Tab", "Bksp", "Del", "Ins", "Help", "Undo",
  571.           "Home", "", "", "", "", "Enter", "ISO", "Space" }, fmt[]="F%d",
  572.           kpfmt[]="kp %c";
  573.  
  574.   key = is_main ? &set.wind_keys[xkey] : &apf.open_key+fknum;
  575.   set_if( o, KOSHIFT, key->shift&3 );
  576.   set_if( o, KOCNTRL, key->shift&4 );
  577.   set_if( o, KOALT, key->shift&8 );
  578.   *(ptr = o[KOKEY].ob_spec.free_string) = '\0';
  579.   if( (c = key->ascii) != 0 )
  580.     if( c == ' ' ) strcpy( ptr, "Space" );
  581.     else
  582.     {
  583.       *ptr++ = c;
  584.       *ptr = 0;
  585.     }
  586.   else
  587.   {
  588.   c = key->scan;
  589.   if( c==0x74 ) c=0x4d;
  590.   else if( c==0x73 ) c=0x4b;
  591.   else if( c==0x77 ) c=0x47;
  592.   else if( c>=0x78 && c<=0x83 ) c -= 0x76;
  593.   for( i=0; i<sizeof(keycode); i++ )
  594.     if( keycode[i] == c ) strcpy( ptr, keynam[i] );
  595.   if( c >= 0x3b && c <= 0x44 ) x_sprintf( ptr, fmt, c-0x3a );
  596.   else if( c >= 0x54 && c <= 0x5d ) x_sprintf( ptr, fmt, c-0x53 );
  597.   if( !*ptr )
  598.   {
  599.     c2 = *(Keytbl( (void *)-1L, (void *)-1L, (void *)-1L )->unshift + c);
  600.     if( c >= 0x63 && c <= 0x72 || c == 0x4a || c == 0x4e )
  601.         x_sprintf( ptr, kpfmt, c2 );
  602.     else
  603.     {
  604.       *ptr++ = c2;
  605.       *ptr = '\0';
  606.     }
  607.   }
  608.   }
  609.   rsrc_gaddr( 15, is_main ? S0+xkey : FLK0+fknum, &p );
  610.   o[KOCNTRL-1].ob_spec.free_string = *p;
  611.   if( !is_main )
  612.   {
  613.     o[KOMENU-1].ob_spec.free_string = flagmode ? app[tasknum-1].name+2 :
  614.         apf.desc[0] ? apf.desc : apf.name;
  615.     if( flagmode || flagnum ) o[KOMENU].ob_state &= ~DISABLED;
  616.     else o[KOMENU].ob_state |= DISABLED;
  617.   }
  618.   if( draw )
  619.   {
  620.     if( !is_main ) x_wdial_draw( form[6].handle, KOMENU-1, 8 );
  621.     x_wdial_draw( is_main ? form[0].handle : form[6].handle, KOCNTRL-1, 8 );
  622.   }
  623. }
  624.  
  625. int get_prefer( OB_PREFER **op )
  626. {
  627.   int ret;
  628.   
  629.   switch( dattnum )
  630.   {
  631.     case 0:
  632.       *op = set.color_root;
  633.       ret = DOSBOX;
  634.       break;
  635.     case 1:
  636.       *op = set.color_3D;
  637.       ret = DOS3D;
  638.       break;
  639.     case 2:
  640.       *op = set.color_exit;
  641.       ret = DOSEXIT;
  642.       break;
  643.     case 3:
  644.       *op = set.color_other;
  645.       ret = DOSOTHER;
  646.       break;
  647.   }
  648.   *op += color_mode;
  649.   return ret;
  650. }
  651.  
  652. void d_obj( int truth, unsigned int *state, int bit, OBJECT *o, int obj )
  653. {
  654.   if( truth ) *state |= bit;
  655.   set_if( o, obj, truth );
  656. }
  657.  
  658. void d_sample( OBJECT *o, int num, int val )
  659. {
  660.   o[num].ob_spec.index = (o[num].ob_spec.index&0xFFFF0000L) |
  661.       (unsigned int)(num==DOPSAMP ? patterns[val+PFIL0].ob_spec.index :
  662.       colors[val+PCOL0].ob_spec.index);
  663. }
  664.  
  665. void d_stat( OBJECT *o, int draw )
  666. {
  667.   OB_PREFER *op;
  668.   unsigned int obj, *state;
  669.   OBJECT *ch;
  670.  
  671.   obj = get_prefer( &op );
  672.   ch = &o[obj];
  673.   *(state = &ch->ob_state) = X_MAGIC;
  674.   d_obj( op->s.outlined, state, OUTLINED,  o, DOUTLINE );
  675.   d_obj( op->s.shadowed, state, SHADOWED,  o, DSHADOW );
  676.   d_obj( op->s.draw_3D,  state, X_DRAW3D,  o, D3D );
  677.   d_obj( op->s.rounded,  state, X_ROUNDED, o, DROUND );
  678.   set_if( o, DOPAQUE, op->s.textmode );
  679.   if( obj==DOSBOX ) ch->ob_spec.index =
  680.       (ch->ob_spec.index&0xFFFF0000L) | (unsigned int)op->l;
  681.   else
  682.       ch->ob_spec.tedinfo->te_color = (unsigned int)op->l;
  683.   d_sample( o, DOPSAMP,   op->s.fillpattern );
  684.   d_sample( o, DOPSAMP+1, op->s.interiorcol );
  685.   d_sample( o, DOPSAMP+2, op->s.textcol );
  686.   d_sample( o, DOPSAMP+3, op->s.framecol );
  687.   if( draw&1 ) x_wdial_draw( form[2].handle, obj==DOSBOX ? DOSBOX-1 : DOSBOX, 8 );
  688.   if( draw&2 ) x_wdial_draw( form[2].handle, DOBOX, 8 );
  689.   if( draw&4 ) x_wdial_draw( form[2].handle, DOSBOX2, 8 );
  690. }
  691.  
  692. int d_init( OBJECT *o )
  693. {
  694.   int old;
  695.   
  696.   get_set();
  697.   old = dattnum;
  698.   for( dattnum=0; dattnum<4; dattnum++ )
  699.     if( dattnum!=old ) d_stat( o, 0 );
  700.   dattnum = old;
  701.   d_stat( o, 0 );    /* do the current one last */
  702.   return 1;
  703. }
  704.  
  705. unsigned int do_popup( OBJECT *o, int obj, OBJECT *pop, unsigned int val )
  706. {
  707.   MENU m, out;
  708.   int x, y;
  709.   
  710.   m.mn_tree = pop;
  711.   m.mn_menu = 0;
  712.   m.mn_item = val+1;
  713.   m.mn_scroll = 1;
  714.   objc_offset( o, obj, &x, &y );
  715.   if( menu_popup( &m, x, y, &out ) ) return out.mn_item-1;
  716.   return val;
  717. }
  718.  
  719. int d_touch( OBJECT *o, int num )
  720. {
  721.   OB_PREFER *op;
  722.   
  723.   if( num>=DOOUT && num<=DOOTHER )
  724.   {
  725.     if( (num-=DOOUT) != dattnum )
  726.     {
  727.       dattnum = num;
  728.       d_stat( o, 2|4 );
  729.     }
  730.   }
  731.   else
  732.   {
  733.     get_prefer( &op );
  734.     switch( num )
  735.     {
  736.       case DOUTLINE:
  737.         op->s.outlined ^= 1;
  738.         break;
  739.       case DSHADOW:
  740.         op->s.shadowed ^= 1;
  741.         break;
  742.       case D3D:
  743.         op->s.draw_3D ^= 1;
  744.         break;
  745.       case DROUND:
  746.         op->s.rounded ^= 1;
  747.         break;
  748.       case DOPAQUE:
  749.         op->s.textmode ^= 1;
  750.         break;
  751.       case DOPLEFT:
  752.         op->s.fillpattern--;
  753.         break;
  754.       case DOPRT:
  755.         op->s.fillpattern++;
  756.         break;
  757.       case DOPAT:
  758.         op->s.fillpattern = do_popup( o, DOPAT, patterns, op->s.fillpattern );
  759.         break;
  760.       case DOPLEFT+3:
  761.         op->s.interiorcol--;
  762.         break;
  763.       case DOPRT+3:
  764.         op->s.interiorcol++;
  765.         break;
  766.       case DOPAT+3:
  767.         op->s.interiorcol = do_popup( o, DOPAT+3, colors, op->s.interiorcol );
  768.         break;
  769.       case DOPLEFT+6:
  770.         op->s.textcol--;
  771.         break;
  772.       case DOPRT+6:
  773.         op->s.textcol++;
  774.         break;
  775.       case DOPAT+6:
  776.         op->s.textcol = do_popup( o, DOPAT+6, colors, op->s.textcol );
  777.         break;
  778.       case DOPLEFT+9:
  779.         op->s.framecol--;
  780.         break;
  781.       case DOPRT+9:
  782.         op->s.framecol++;
  783.         break;
  784.       case DOPAT+9:
  785.         op->s.framecol = do_popup( o, DOPAT+9, colors, op->s.framecol );
  786.         break;
  787.     }
  788.     d_stat( o, 1|4 );
  789.   }
  790.   return -1;
  791. }
  792.  
  793. int d_exit( OBJECT *o, int num )
  794. {
  795.   if( num==DOOK ) x_settings( 1, sizeof(SETTINGS), &set );
  796.   o++;
  797.   return 1;
  798. }
  799.  
  800. void close_vdi(void)
  801. {
  802.   if( vdi_hand )
  803.   {
  804.     if( has_gdos ) vst_unload_fonts( vdi_hand, 0 );
  805.     v_clsvwk( vdi_hand );
  806.     vdi_hand = 0;
  807.   }
  808. }
  809.  
  810. void text_size( OBJECT *o, char *string, int center )
  811. {
  812.   int i;
  813.  
  814.   (char *)(o->ob_spec.userblk->ub_parm) = string;
  815.   if( !string ) o->ob_width = font_wid;
  816.   else if( (o->ob_width = strlen(string) * font_wid) > o[-1].ob_width )
  817.   {
  818.     o->ob_width = (i=o[-1].ob_width / font_wid) * font_wid;
  819.     o->ob_spec.userblk->ub_parm += strlen(string)-i;
  820.   }
  821.   o->ob_height = font_ht;
  822.   if( center ) o->ob_x = (o[-1].ob_width - o->ob_width + 1) / 2;
  823.   o->ob_y = (o[-1].ob_height - font_ht + 1) / 2;
  824. }
  825.  
  826. void wo_update( OBJECT *o, int draw )
  827. {
  828.   int w, h, cw, ch;
  829.   
  830.   w = o[XWOUTER].ob_width;
  831.   h = o[XWOUTER].ob_height;
  832.   cw = font_wid + fontinfo.gadget_wid;
  833.   ch = font_ht + fontinfo.gadget_ht;
  834.   o[XWMOVE].ob_width = o[XWBACK].ob_width = o[XWFULL].ob_width =
  835.       o[XWUP].ob_width = o[XWVBIGSL].ob_width = o[XWVSMLSL].ob_width = cw;
  836.   o[XWMOVE].ob_height = o[XWBACK].ob_height = o[XWFULL].ob_height =
  837.       o[XWUP].ob_height = o[XWINFO].ob_height = o[XWVSMLSL].ob_height = ch;
  838.   o[XWMOVE].ob_width = w - cw*2 + 2;
  839.   o[XWBACK].ob_x = w - cw*2 + 1;
  840.   o[XWFULL].ob_x = o[XWUP].ob_x = o[XWVBIGSL].ob_x = w - cw;
  841.   o[XWINFO].ob_y = ch - 1;
  842.   o[XWINFO].ob_width = w;
  843.   o[XWUP].ob_y = (ch-1)*2;
  844.   o[XWVBIGSL].ob_y = (ch-1)*3;
  845.   o[XWVBIGSL].ob_height = h - (ch-1)*3;
  846.   if( o[XWUP].ob_y + ch > h ) o[XWUP].ob_height = -5;
  847.   if( o[XWINFO].ob_y + ch > h ) o[XWINFO].ob_height = -5;
  848.   if( o[XWVSMLSL].ob_y + o[XWVBIGSL].ob_y + ch > h ) o[XWVSMLSL].ob_height = -5;
  849.   text_size( &o[XWMOVET], mover_text, 1 );
  850.   text_size( &o[XWINFOT], info_text, 0 );
  851.   text_size( &o[XWBACKT], 0L, 1 );
  852.   text_size( &o[XWFULLT], 0L, 1 );
  853.   text_size( &o[XWUPT], 0L, 1 );
  854.   if( draw ) x_wdial_draw( form[3].handle, XWOUTER, 8 );
  855.   x_appl_font( 1, 0, &fontinfo );
  856. }
  857.  
  858. void new_point( OBJECT *o, int draw )
  859. {
  860.   int dum;
  861.  
  862.   fontinfo.point_size = vst_point( vdi_hand, fontinfo.point_size,
  863.       &dum, &dum, &font_wid, &font_ht );
  864.   x_sprintf( o[WOPT].ob_spec.free_string, "%d", fontinfo.point_size );
  865.   wo_update( o, draw );
  866.   if( draw ) x_wdial_draw( form[3].handle, WOPT, 8 );
  867. }
  868.  
  869. void new_gadget( OBJECT *o, int draw )
  870. {
  871.   x_sprintf( o[WOWID].ob_spec.free_string, "%d", fontinfo.gadget_wid );
  872.   x_sprintf( o[WOHT].ob_spec.free_string, "%d", fontinfo.gadget_ht );
  873.   wo_update( o, draw );
  874.   if( draw )
  875.   {
  876.     x_wdial_draw( form[3].handle, WOWID, 8 );
  877.     x_wdial_draw( form[3].handle, WOHT, 8 );
  878.   }
  879. }
  880.  
  881. void set_fnum( OBJECT *o, int i, int draw )
  882. {
  883.   int dum;
  884.  
  885.   font_num = i;
  886.   o[WOFONT].ob_spec.free_string = fontpop[i+1].ob_spec.free_string+1;
  887.   if( draw ) x_wdial_draw( form[3].handle, WOFONT, 8 );
  888.   vst_font( vdi_hand, fontinfo.font_id = font_id[i] );
  889.   vst_alignment( vdi_hand, 0, 5, &dum, &dum );
  890.   new_point( o, draw );
  891. }
  892.  
  893. void get_font( OBJECT *o, int draw )
  894. {
  895.   int i;
  896.   
  897.   x_appl_font( 0, 0, &fontinfo0 );
  898.   memcpy( &fontinfo, &fontinfo0, sizeof(fontinfo) );
  899.   o[WOFONT].ob_spec.free_string = "";
  900.   font_num = 0;
  901.   for( i=0; i<fonts; i++ )
  902.     if( font_id[i] == fontinfo.font_id )
  903.     {
  904.       set_fnum( o, i, draw );
  905.       break;
  906.     }
  907. }
  908.  
  909. int cdecl win_text( PARMBLK *pb )
  910. {
  911.   int clip[4];
  912.   char *s, temp[2];
  913.   
  914.   clip[2] = (clip[0] = pb->pb_xc) + pb->pb_wc - 1;
  915.   clip[3] = (clip[1] = pb->pb_yc) + pb->pb_hc - 1;
  916.   vs_clip( vdi_hand, 1, clip );
  917.   if( (s = (char *)(pb->pb_parm)) == 0 )
  918.   {
  919.     temp[0] = pb->pb_tree[pb->pb_obj].ob_type>>8;
  920.     temp[1] = 0;
  921.     s = temp;
  922.     vswr_mode( vdi_hand, MD_TRANS );
  923.   }
  924.   else vswr_mode( vdi_hand, MD_REPLACE );
  925.   v_gtext( vdi_hand, pb->pb_x, pb->pb_y, s );
  926.   return pb->pb_currstate;
  927. }
  928.  
  929. void set_onechar( OBJECT *o, USERBLK *ub )
  930. {
  931.   o->ob_type = (o->ob_spec.obspec.character<<8) | G_USERDEF;
  932.   o->ob_spec.userblk = ub;
  933. }
  934.  
  935. int wo_init( OBJECT *o )
  936. {
  937.   int i, j, total, id, min, max, dum[5], maxw, wid;
  938.   char namebuf[32];
  939.   static USERBLK ub_move, ub_info, ub_onechar;
  940.   
  941.   if( vdi_hand ) return 1;    /* just in case it's already open */
  942.   vdi_hand = graf_handle( dum, dum, dum, dum );
  943.   work_in[0] = Getrez() + 2;
  944.   v_opnvwk( work_in, &vdi_hand, work_out );
  945.   if( !vdi_hand )
  946.   {
  947.     alert( ALNOVDI );
  948.     return 0;
  949.   }
  950.   total = work_out[10];
  951.   has_gdos = vq_gdos();
  952.   if( has_gdos )
  953.   {
  954.     graf_mouse( BUSYBEE, 0L );
  955.     total += vst_load_fonts( vdi_hand, 0 );
  956.     graf_mouse( ARROW, 0L );
  957.   }
  958.   for( i=1, fonts=0; i<=total && fonts<16; i++ )
  959.   {
  960.     id = vqt_name( vdi_hand, i, namebuf );
  961.     if( id != -1 )
  962.     {
  963.       vst_font( vdi_hand, id );
  964.       vqt_fontinfo( vdi_hand, &min, &max, dum, &maxw, dum );
  965.       for( j=min; j<=max; j++ )
  966.       {
  967.         vqt_width( vdi_hand, j, &wid, dum, dum );
  968.         if( wid != maxw ) break;
  969.       }
  970.       if( j>max )
  971.       {
  972.         font_id[fonts] = id;
  973.         strncpy( fontpop[++fonts].ob_spec.free_string+1,
  974.             id==1 ? *sys_font : namebuf, 16 );
  975.         objc_add( fontpop, 0, fonts );
  976.       }
  977.     }
  978.   }
  979.   fontpop[0].ob_height = fontpop[1].ob_height*fonts;
  980.   if( o[XWMOVET].ob_type != G_USERDEF )
  981.   {
  982.     o[XWMOVET].ob_type = o[XWINFOT].ob_type = G_USERDEF;
  983.     mover_text = o[XWMOVET].ob_spec.free_string;
  984.     o[XWMOVET].ob_spec.userblk = &ub_move;
  985.     info_text = o[XWINFOT].ob_spec.free_string;
  986.     o[XWINFOT].ob_spec.userblk = &ub_info;
  987.     set_onechar( &o[XWBACKT], &ub_onechar );
  988.     set_onechar( &o[XWFULLT], &ub_onechar );
  989.     set_onechar( &o[XWUPT], &ub_onechar );
  990.     ub_move.ub_code = ub_info.ub_code = ub_onechar.ub_code = win_text;
  991.   }
  992.   get_font( o, 0 );
  993.   new_gadget( o, 0 );
  994.   return 1;
  995. }
  996.  
  997. int wo_exit( OBJECT *o, int num )
  998. {
  999.   switch( num )
  1000.   {
  1001.     case WOFONT:
  1002.       if( fonts>1 ) set_fnum( o, do_popup( o, WOFONT, fontpop, font_num ), 1 );
  1003.       return 0;
  1004.     case WODFLT:
  1005.       fontinfo.font_id = fontinfo.point_size = fontinfo.gadget_wid =
  1006.           fontinfo.gadget_ht = -2;    /* reset to defaults */
  1007.       x_appl_font( 1, 0, &fontinfo );    /* set */
  1008.       x_appl_font( 0, 0, &fontinfo );    /* get new values */
  1009.       get_font( o, 1 );
  1010.       new_gadget( o, 1 );
  1011.       return 0;
  1012.     case WOOK:
  1013.       if( memcmp( &fontinfo, &fontinfo0, sizeof(fontinfo) ) ) alert( ALSAVE );
  1014.       return 1;
  1015.     default:
  1016.       x_appl_font( 1, 0, &fontinfo0 );
  1017.       return 1;
  1018.   }
  1019. }
  1020.  
  1021. int wo_touch( OBJECT *o, int num )
  1022. {
  1023.   int pt, dum;
  1024.   
  1025.   switch( num )
  1026.   {
  1027.     case WOPUP:
  1028.       for( pt=fontinfo.point_size+1; pt<25; pt++ )
  1029.         if( vst_point( vdi_hand, pt, &dum, &dum, &dum, &dum ) == pt )
  1030.         {
  1031.           fontinfo.point_size = pt;
  1032.           new_point( o, 1 );
  1033.           break;
  1034.         }
  1035.       break;
  1036.     case WOPDWN:
  1037.       if( vst_point( vdi_hand, pt=fontinfo.point_size-1, &dum, &dum,
  1038.           &dum, &dum ) <= pt )
  1039.       {
  1040.         fontinfo.point_size = pt;
  1041.         new_point( o, 1 );
  1042.       }
  1043.       break;
  1044.     case WOWUP:
  1045.       if( fontinfo.gadget_wid<25 )
  1046.       {
  1047.         fontinfo.gadget_wid++;
  1048.         new_gadget( o, 1 );
  1049.       }
  1050.       break;
  1051.     case WOWDWN:
  1052.       if( fontinfo.gadget_wid>0 )
  1053.       {
  1054.         fontinfo.gadget_wid--;
  1055.         new_gadget( o, 1 );
  1056.       }
  1057.       break;
  1058.     case WOHUP:
  1059.       if( fontinfo.gadget_ht<25 )
  1060.       {
  1061.         fontinfo.gadget_ht++;
  1062.         new_gadget( o, 1 );
  1063.       }
  1064.       break;
  1065.     case WOHDWN:
  1066.       if( fontinfo.gadget_ht>0 )
  1067.       {
  1068.         fontinfo.gadget_ht--;
  1069.         new_gadget( o, 1 );
  1070.       }
  1071.       break;
  1072.   }
  1073.   num++;
  1074.   return -1;
  1075. }
  1076.  
  1077. void calc_bord( int type, OBJECT *tree, GRECT *g )
  1078. {
  1079.   wind_calc( WC_BORDER, type, tree[0].ob_x, tree[0].ob_y,
  1080.       tree[0].ob_width, tree[0].ob_height, &g->g_x, &g->g_y,
  1081.       &g->g_w, &g->g_h );
  1082. }
  1083.  
  1084. void start_form( int fnum, int tnum, int type )
  1085. {
  1086.   FORM *f = &form[fnum];
  1087.   int dum, hand;
  1088.   GRECT out;
  1089.   
  1090.   if( f->handle>0 ) wind_set( f->handle, WF_TOP );
  1091.   else
  1092.   {
  1093.     if( !f->tree )
  1094.     {
  1095.       rsrc_gaddr( 0, tnum, &f->tree );
  1096.       f->tree[1].ob_flags |= HIDETREE;
  1097.       calc_bord( type, f->tree, &out );
  1098.       out.g_x = (max.g_w-out.g_w)/2 + max.g_x;
  1099.       out.g_y = (max.g_h-out.g_h)/2 + max.g_y;
  1100.       wind_calc( WC_WORK, type, out.g_x, out.g_y, out.g_w, out.g_h,
  1101.          &f->tree[0].ob_x, &f->tree[0].ob_y, &dum, &dum );
  1102.     }
  1103.     else calc_bord( type, f->tree, &out );
  1104.     if( (hand=wind_create( type, out.g_x, out.g_y, out.g_w, out.g_h )) > 0 )
  1105.     {
  1106.       f->handle = hand;
  1107.       if( (*f->init)( f->tree ) )
  1108.       {
  1109.         wind_set( hand, X_WF_DIALOG, f->tree );
  1110.         wind_set( hand, WF_NAME, f->tree[1].ob_spec.free_string );
  1111.         wind_open( hand, out.g_x, out.g_y, out.g_w, out.g_h );
  1112.       }
  1113.       else close_wind( &f->handle );
  1114.     }
  1115.   }
  1116. }
  1117.  
  1118. void use_form( int hand, int num )
  1119. {
  1120.   int i, j, but;
  1121.   FORM *f;
  1122.  
  1123.   if( !hand ) return;
  1124.   for( f=&form[0]; f->init; f++ )
  1125.     if( f->handle == hand )
  1126.     {
  1127.       but = num&0x7FFF;
  1128.       if( f->tree[but].ob_flags & TOUCHEXIT )
  1129.         if( f->touch && (j=(*f->touch)( f->tree, but )) >= 0 )
  1130.             x_wdial_draw( f->handle, j, 8 );
  1131.       if( f->tree[but].ob_flags&EXIT )
  1132.       {
  1133.         f->tree[but].ob_state &= ~SELECTED;
  1134.         if( f->exit && (*f->exit)( f->tree, num ) ) close_wind(&f->handle);
  1135.         else x_wdial_draw( f->handle, but, 8 );
  1136.       }
  1137.       return;
  1138.     }
  1139. }
  1140.  
  1141. char chksum( char *buf )
  1142. {
  1143.   char chk=0;
  1144.   
  1145.   while( *buf ) chk = (chk + *buf++)<<1;
  1146.   return chk;
  1147. }
  1148.  
  1149. int qsc( struct App *ap1, struct App *ap2 )
  1150. {
  1151.   return( strcmp( ap1->name, ap2->name ) );
  1152. }
  1153.  
  1154. void set_term_sleep(void)
  1155. {
  1156.   menu_ienable( menu, TERM, tasknum>0 );
  1157.   menu_ienable( menu, SLEEP, tasknum>0 );
  1158.   menu_icheck( menu, SLEEP, tasknum>0 && (app[tasknum-1].asleep&1) );
  1159. }
  1160.  
  1161. int task_list(void)
  1162. {
  1163.   static char chk=0;
  1164.   char nchk;
  1165.   int i, j, type, sleep;
  1166.   struct App *a;
  1167.  
  1168.   for( nchk=0, j=0, i=1, a=&app[0]; i<65; i++, a++ )
  1169.     if( appl_search( j, a->name+3, &type, &a->num ) )
  1170.     {
  1171.       a->asleep = x_appl_sleep( a->num, -1 );
  1172.       if( a->asleep&2 ) strcpy( a->name+2, a->name+3 );
  1173.       else a->name[2] = ' ';
  1174.       nchk += chksum(a->name+3) + type + a->asleep;
  1175.       a->name[0] = type!=4 ? ' ' : '°';
  1176.       a->name[1] = ' ';
  1177.       j=1;
  1178.     }
  1179.     else break;
  1180.   i--;
  1181.   qsort( app, i, sizeof(app[0]), qsc );
  1182.   if( i != apps || chk != nchk )
  1183.   {
  1184.     apps = i;
  1185.     chk = nchk;
  1186.     blank[0].ob_head = blank[0].ob_tail = -1;
  1187.     for( i=1, a=&app[0]; i<=apps; i++, a++ )
  1188.     {
  1189.       memcpy( blank+i, new, sizeof(OBJECT) );
  1190.       blank[i].ob_y = (i-1)*char_h;
  1191.       blank[i].ob_spec.free_string = a->name;
  1192.       if( a->asleep&1 ) blank[i].ob_flags |= X_ITALICS;
  1193.       if( !(a->asleep&2) ) blank[i].ob_state |= X_SMALLTEXT;
  1194.       if( i==tasknum ) blank[i].ob_state |= SELECTED;
  1195.       objc_add( blank, 0, i );
  1196.     }
  1197.     return 1;
  1198.   }
  1199.   return 0;
  1200. }
  1201.  
  1202. void set_bl_height(void)
  1203. {
  1204.   int i;
  1205.   
  1206.   blank[0].ob_height = (i=apps*char_h) > winner.g_h ? i : winner.g_h;
  1207. }
  1208.  
  1209. void get_inner(void)
  1210. {
  1211.   wind_calc( WC_WORK, WIN_TYPE, wsize.g_x, wsize.g_y, wsize.g_w, wsize.g_h,
  1212.       &winner.g_x, &winner.g_y, &winner.g_w, &winner.g_h );
  1213.   new[0].ob_x = 2;
  1214.   blank[0].ob_width = winner.g_w;
  1215.   set_bl_height();
  1216. }
  1217.  
  1218. void get_outer(void)
  1219. {
  1220. /*  winner.g_w = (winner.g_w+5)/8*8 + 2;*/
  1221.   winner.g_h = (winner.g_h+(char_h>>1))/char_h*char_h;
  1222.   wind_calc( WC_BORDER, WIN_TYPE, winner.g_x, winner.g_y,
  1223.       winner.g_w, winner.g_h, &wsize.g_x, &wsize.g_y, &wsize.g_w,
  1224.       &wsize.g_h );
  1225. }
  1226.  
  1227. void but_up(void)
  1228. {
  1229.   int b, dum;
  1230.   
  1231.   do
  1232.     graf_mkstate( &dum, &dum, &b, &dum );
  1233.   while( b&1 );
  1234. }
  1235.  
  1236. void tnum_onoff( int handle, int num, int state )
  1237. {
  1238.   x_wdial_change( handle, num, !state ? (blank[num].ob_state&~SELECTED) :
  1239.       (blank[num].ob_state|SELECTED) );
  1240. }
  1241.  
  1242. void opentask( int handle, int num )
  1243. {
  1244.   int msg[8];
  1245.   
  1246. /*  if( app[num-1].asleep&1 ) x_appl_sleep( app[num-1].num, 0 );*/
  1247.   msg[0] = AC_OPEN;
  1248.   msg[2] = 0;
  1249.   msg[4] = -1;
  1250.   appl_write( msg[1] = app[num-1].num, 16, msg );
  1251.   tnum_onoff( handle, num, 0 );
  1252. }
  1253.  
  1254. void set_if( OBJECT *tree, int num, int true )
  1255. {
  1256.   if( true ) tree[num].ob_state |= SELECTED;
  1257.   else tree[num].ob_state &= ~SELECTED;
  1258. }
  1259.  
  1260. int exec_ext( char *path, char *env, int i )
  1261. {
  1262.   char *ptr;
  1263.   
  1264.   if( shel_envrn( &ptr, env ) && *ptr )
  1265.   {
  1266.     strcat( path, i ? "," : "*.{" );
  1267.     strcat( path, ptr );
  1268.     return 1;
  1269.   }
  1270.   return i;
  1271. }
  1272.  
  1273. int spf_alert( char *s, char *s2 )
  1274. {
  1275.   char buf[200];
  1276.   
  1277.   x_sprintf( buf, s, s2 );
  1278.   return( form_alert( 1, buf ) );
  1279. }
  1280.  
  1281. void get_color_mode(void)
  1282. {
  1283.   int work[56], vplanes, vdi_hand;
  1284.  
  1285.   vdi_hand = graf_handle( work, work, work, work );
  1286.   vq_extnd( vdi_hand, 1, work );
  1287.   vplanes = work[4];
  1288.   if( vplanes>=8 ) color_mode = 3;
  1289.   else if( vplanes>=4 ) color_mode = 2;
  1290.   else if( vplanes>=2 ) color_mode = 1;
  1291.   else color_mode = 0;
  1292. }
  1293.  
  1294. int main(void)
  1295. {
  1296.   char **title, **fstitle, path[120], name[13*5+1], temp[150], temp2[80],
  1297.       *ptr, *ptr2, **term_msg, **ptr3, was_open=0;
  1298.   int handle=0, buf[8], but, dum, event, i, etype=MU_MESAG|X_MU_DIALOG,
  1299.       timer, min_ht, min_wid;    /* min_wid is acutally the only width */
  1300.   long cookie;
  1301.   GRECT old;
  1302.   SHWRCMD shwrcmd;
  1303.  
  1304.   apid = appl_init();
  1305.   shel_write( 9, 1, 0, 0L, 0L );
  1306.   /* check to make sure MAGIC is active */
  1307.   if( CJar( 0, my_cookie, &cookie ) != CJar_OK || !cookie )
  1308.   {
  1309.     form_alert( 1, "[1][MAGIC must be present|in order for TASKMAN|to run][Ok]" );
  1310.   }
  1311.   else if( rsrc_load("taskman.rsc") )
  1312.   {
  1313.     get_color_mode();
  1314.     /* default item selector path */
  1315.     path[0] = Dgetdrv()+'A';
  1316.     path[1] = ':';
  1317.     Dgetpath( path+2, 0 );
  1318.     strcat( path, "\\" );
  1319.     /* read extensions from GEM env vars for use in item selector */
  1320.     if( !exec_ext( path, "ACCEXT=", exec_ext( path, "TOSEXT=",
  1321.         exec_ext( path, "GEMEXT=", 0 ) ) ) ) strcat( path, "*.*" );
  1322.     else strcat( path, "}" );
  1323.     name[0] = 0;
  1324.     /* get main window menu tree and initialize root for keybd equivs */
  1325.     rsrc_gaddr( 0, TMENU, &menu );
  1326.     menu[0].ob_state |= X_MAGIC;
  1327.     /* get the popup menus */
  1328.     rsrc_gaddr( 0, PCOLORS, &colors );
  1329.     rsrc_gaddr( 0, PFILLS, &patterns );
  1330.     rsrc_gaddr( 0, PFONTS, &fontpop );
  1331.     /* get other strings used */
  1332.     rsrc_gaddr( 15, TITLE, &title );
  1333.     rsrc_gaddr( 15, FSTITLE, &fstitle );
  1334.     rsrc_gaddr( 15, NEW, &new_flag );
  1335.     rsrc_gaddr( 15, SSYSTEM, &sys_font );
  1336.     /* fix the new object tree used for entries in the task list */
  1337.     rsrc_obfix( new, 0 );
  1338.     appl_getinfo( 0, &char_h, &dum, &dum, &dum );
  1339.     /* set default window width to same size as menu */
  1340.     wsize.g_w = menu[2].ob_width;
  1341.     get_inner();
  1342.     wind_get( 0, WF_WORKXYWH, &max.g_x, &max.g_y, &max.g_w, &max.g_h );
  1343.     /* set the correct name in the menu */
  1344.     menu_register( apid, *title );
  1345.     if( _app )          /* running as PRG */
  1346.     {
  1347.       graf_mouse( ARROW, 0L );
  1348.       goto open;
  1349.     }
  1350.     timer = 500;    /* wait for 5 seconds, normally */
  1351.     for(;;)
  1352.     {
  1353.       event = evnt_multi( etype,  0,0,0,  0,0,0,0,0,
  1354.           0,0,0,0,0,  buf,  timer,0,  &dum, &dum, &dum, &dum, &dum, &dum );
  1355.       timer = 500;
  1356.       if( event&MU_MESAG ) switch( buf[0] )
  1357.       {
  1358.         case AC_OPEN:
  1359. open:     if( handle<=0 )
  1360.           {
  1361.             if( !was_open )
  1362.             {
  1363.               wind_update( BEG_UPDATE );
  1364.               task_list();
  1365.               set_term_sleep();
  1366.               wind_update( END_UPDATE );
  1367.               winner.g_h = apps<16 ? apps*char_h : char_h*16;
  1368.               get_outer();
  1369.             }
  1370.             if( (handle=wind_create( WIN_TYPE,
  1371.                 wsize.g_x, wsize.g_y, wsize.g_w, wsize.g_h )) > 0 )
  1372.             {
  1373.               if( !was_open )
  1374.               {
  1375.                 wind_get( handle, X_WF_MINMAX, &min_wid, &min_ht, &dum, &dum );
  1376.                 if( min_wid < menu[2].ob_width ) min_wid=menu[2].ob_width;
  1377.                 wind_calc( WC_BORDER, WIN_TYPE, 0, 0, (10*8)+4, 0,
  1378.                     &dum, &dum, &buf[0], &dum );
  1379.                 if( min_wid < buf[0] ) min_wid = buf[0];
  1380.                 wsize.g_w = min_wid;
  1381.                 if( wsize.g_h < min_ht ) wsize.g_h = min_ht;
  1382.               }
  1383.               wind_set( handle, X_WF_MINMAX, min_wid, min_ht, min_wid, -1 );
  1384.               get_inner();
  1385.               blank[0].ob_x = winner.g_x;
  1386.               blank[0].ob_y = winner.g_y;
  1387.               wind_set( handle, X_WF_DIALOG, blank );
  1388.               wind_set( handle, X_WF_DIALHT, char_h );
  1389.               wind_set( handle, X_WF_MENU, menu );
  1390.               wind_set( handle, WF_NAME, *title + 2 );
  1391.               wind_open( handle, wsize.g_x, wsize.g_y, wsize.g_w, wsize.g_h );
  1392.               etype |= MU_TIMER;
  1393.               timer = 0;                /* force task list update */
  1394.               was_open=1;
  1395.             }
  1396.             break;
  1397.           }
  1398.           buf[3] = handle;      /* fall through if already open */
  1399.         case WM_TOPPED:
  1400.           wind_set( buf[3], WF_TOP );
  1401.           break;
  1402.         case WM_FULLED:
  1403.           if( buf[3] != handle ) break;
  1404.           buf[4] = wsize.g_x;
  1405.           buf[5] = wsize.g_y;
  1406.           wind_get( handle, X_WF_MINMAX, &dum, &dum, &buf[6], &buf[7] );
  1407.         case WM_MOVED:
  1408.         case WM_SIZED:
  1409.           if( buf[3]==handle )
  1410.           {
  1411.             old = wsize;
  1412.             wsize = *(GRECT *)&buf[4];
  1413.             get_inner();
  1414.             if( winner.g_h > blank[0].ob_height ) winner.g_h =
  1415.                 blank[0].ob_height;
  1416.             get_outer();
  1417.             *(GRECT *)&buf[4] = wsize;
  1418.           }
  1419.           wind_set( buf[3], WF_CURRXYWH, buf[4], buf[5], buf[6], buf[7] );
  1420.           /* force a redraw if it wouldn't otherwise happen */
  1421.           if( buf[3]==handle && wsize.g_w <= old.g_w && wsize.g_h <= old.g_h &&
  1422.               (wsize.g_w != old.g_w || wsize.g_h != old.g_h) ) wind_set( handle,
  1423.               X_WF_DIALOG, blank );
  1424.           break;
  1425.         case WM_CLOSED:
  1426.           if( buf[3]==handle )
  1427.           {
  1428. close:      close_wind(&handle);
  1429.             etype &= ~MU_TIMER;
  1430.             if( _app )
  1431.             {
  1432.               appl_exit();
  1433.               return 0;
  1434.             }
  1435.           }
  1436.           break;
  1437.         case AC_CLOSE:
  1438.           handle=0;
  1439.           close_vdi();
  1440.           for( i=0; form[i].init; i++ )
  1441.             form[i].handle = 0;
  1442.           etype = MU_MESAG|X_MU_DIALOG;
  1443.           break;
  1444.         case WM_ARROWED:
  1445.           if( form[0].handle>0 && buf[3]==form[0].handle ) new_key( buf[4], 0 );
  1446.           break;
  1447.         case AP_TERM:
  1448.           appl_exit();
  1449.           return 0;
  1450.         case SHUT_COMPLETED:
  1451.           if( buf[3]==0 ) alert( ALNOSHUT );
  1452.           else
  1453.           {
  1454.             appl_exit();
  1455.             return 0;
  1456.           }
  1457.           break;
  1458.         case RESCH_COMPLETED:
  1459.           if( buf[3]==0 ) alert( ALREZ );
  1460.           else
  1461.           {
  1462.             appl_exit();
  1463.             return 0;
  1464.           }
  1465.           break;
  1466.         case CH_EXIT:
  1467.           if( buf[4] )
  1468.           {
  1469.             appl_search( -1, temp2, &dum, &but );
  1470.             rsrc_gaddr( 15, ALTERM, &term_msg );
  1471.             rsrc_gaddr( 15, SUNKNOWN, &ptr3 );
  1472.             x_sprintf( temp, *term_msg, but==buf[3] ? temp2 : *ptr3, buf[4] );
  1473.             if( buf[4]<0 ) x_form_error( temp, buf[4] );
  1474.             else
  1475.             {
  1476.               rsrc_gaddr( 15, SUNDEF, &ptr3 );
  1477.               spf_alert( temp, *ptr3 );
  1478.             }
  1479.           }
  1480.           timer = 0;
  1481.           break;
  1482.         case X_WM_SELECTED:
  1483.           if( form[0].handle>0 && buf[3]==form[0].handle )
  1484.             if( buf[4]==WMOVE )
  1485.             {
  1486.               wind_get( buf[3], WF_CURRXYWH, buf+4, buf+5, buf+6, buf+7 );
  1487.               if( graf_dragbox( buf[6], buf[7], buf[4], buf[5], 
  1488.                   max.g_x-buf[6], max.g_y, max.g_w<<1, max.g_h<<1, buf+4, buf+5 ) )
  1489.                   wind_set( buf[3], WF_CURRXYWH, buf[4], buf[5], buf[6], buf[7] );
  1490.             }
  1491.             else new_key( buf[4], 1 );
  1492.           break;
  1493.         case X_MN_SELECTED:
  1494.           switch( buf[4] )
  1495.           {
  1496.             case OPEN:
  1497.               if( tasknum>0 )
  1498.               {
  1499.                 opentask( handle, tasknum );
  1500.                 tasknum=0;
  1501.                 set_term_sleep();
  1502.               }
  1503.               else if( x_fsel_input( path, sizeof(path), name, 5,
  1504.                   &but, *fstitle ) && but )
  1505.               {
  1506.                 strcpy( temp, path );
  1507.                 if( (ptr=strrchr(temp,'\\')) == 0 ) ptr=temp;
  1508.                 else ptr++;
  1509.                 for( ptr2=name; *ptr2; ptr2+=strlen(ptr2)+1 )
  1510.                 {
  1511.                   strcpy( ptr, ptr2 );
  1512.                   shwrcmd.name = temp;
  1513.                   shwrcmd.dflt_dir = path;
  1514.                   if( !shel_write( (1<<10)|0, 1, 0, (char *)&shwrcmd, "" ) )
  1515.                   {
  1516.                     rsrc_gaddr( 15, ALOPEN, &ptr3 );
  1517.                     spf_alert( *ptr3, ptr2 );
  1518.                   }
  1519.                 }
  1520.               }
  1521.               break;
  1522.             case QUIT:
  1523.               if( handle ) close_wind(&handle);
  1524.               for( i=0; form[i].init; i++ )
  1525.                 if( form[i].handle ) close_wind(&form[i].handle);
  1526.               etype = MU_MESAG|X_MU_DIALOG;
  1527.               if( _app )
  1528.               {
  1529.                 appl_exit();
  1530.                 return 0;
  1531.               }
  1532.               break;
  1533.             case TERM:
  1534.               if( tasknum>0 )
  1535.                 if( x_appl_term( app[tasknum-1].num, 0, 1 ) ) timer = 0;
  1536.               break;
  1537.             case SLEEP:
  1538.               if( tasknum>0 )
  1539.               {
  1540.                 x_appl_sleep( app[tasknum-1].num, (app[tasknum-1].asleep&1)^1 );
  1541.                 timer = 0;
  1542.               }
  1543.               break;
  1544.             case SHUT:
  1545.               if( alert( ALSHUT ) == 1 ) shel_write( 4, 1, 0, 0L, 0L );
  1546.               break;
  1547.             case KEYBOARD:
  1548.               start_form( 0, KEYOPTS, CLOSER|FULLER|MOVER|INFO|UPARROW|DNARROW|VSLIDE|LFARROW|RTARROW|HSLIDE );
  1549.               break;
  1550.             case MISC:
  1551.               start_form( 1, MISCOPTS, NAME|MOVER );
  1552.               break;
  1553.             case DIALOGS:
  1554.               start_form( 2, DIALOPTS, NAME|MOVER );
  1555.               break;
  1556.             case TWINDOWS:
  1557.               start_form( 3, WINDOPTS, NAME|MOVER );
  1558.               break;
  1559.             case VIDEO:
  1560.               start_form( 4, VIDOPTS, NAME|MOVER );
  1561.               break;
  1562.             case FLAGS:
  1563.               start_form( 5, FLAGOPTS, NAME|MOVER );
  1564.               break;
  1565.             case SAVE:
  1566.               x_shel_put( X_SHLOADSAVE, 0L );
  1567.               break;
  1568.             case RELOAD:
  1569.               x_shel_get( X_SHLOADSAVE, 0, 0L );
  1570.               break;
  1571.           }
  1572.           menu_tnormal( menu, buf[3], 1 );
  1573.           break;
  1574.       }
  1575.       if( event&X_MU_DIALOG )
  1576.       {
  1577.         but = buf[2]&0x7fff;
  1578.         if( buf[3]==handle )
  1579.           if( buf[2]&0x8000 )
  1580.           {
  1581.             if( but ) opentask( handle, but );
  1582.             else if( tasknum>0 ) tnum_onoff( handle, tasknum, 0 );
  1583.             tasknum=0;
  1584.             set_term_sleep();
  1585.           }
  1586.           else
  1587.           {
  1588.             /* a DISABLED object does not get selected automatically,
  1589.                so we have to handle this ourselves */
  1590.             if( tasknum>0 && tasknum!=but ) tnum_onoff( handle, tasknum, 0 );
  1591.             if( but && blank[but].ob_state&DISABLED ) tnum_onoff( handle, but, 1 );
  1592.             tasknum=but;
  1593.             but_up();
  1594.             set_term_sleep();
  1595.           }
  1596.         else use_form( buf[3], buf[2] );
  1597.       }
  1598.       if( event&MU_TIMER && handle>0 )
  1599.       {
  1600.         wind_update( BEG_UPDATE );
  1601.         if( task_list() )
  1602.         {
  1603.           set_bl_height();
  1604.           wind_calc( WC_BORDER, WIN_TYPE, 0, 0, blank[0].ob_width,
  1605.               blank[0].ob_height, &dum, &dum, buf, buf+1 );
  1606.           wind_set( handle, X_WF_MINMAX, -1, -1, buf[0], buf[1] );
  1607.           if( tasknum>0 ) blank[tasknum].ob_state &= ~SELECTED;
  1608.           tasknum = 0;
  1609.           set_term_sleep();
  1610.           wind_set( handle, X_WF_DIALOG, blank );
  1611.         }
  1612.         wind_update( END_UPDATE );
  1613.       }
  1614.     }
  1615.   }
  1616.   else form_alert( 1, "[1][|TASKMAN.RSC not found!][Ok]" );
  1617.   if( _app )
  1618.   {
  1619.     appl_exit();
  1620.     return 0;
  1621.   }
  1622.   for(;;)
  1623.   {
  1624.     evnt_mesag(buf);
  1625.     if( buf[0]==AP_TERM )
  1626.     {
  1627.       appl_exit();
  1628.       return 0;
  1629.     }
  1630.   }
  1631. }
  1632.