home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_08 / weber / region.c < prev    next >
Text File  |  1993-03-13  |  18KB  |  469 lines

  1. /***************************************************************
  2.  * file: REGION.C
  3.  * purpose: Demonstration of region finding with cellular automata
  4.  * system: Written for the flash graphics library in Zortech 3.0
  5.  * copyright: 1992 by David Weber.  All rights reserved.
  6.  *  This software can be used for any purpose as object, library or executable.
  7.  *  It cannot be sold for profit as source code.
  8.  * history:
  9.  *  01-13-92 - initial code
  10.  *  01-31-93 - the gui code is now obsolete, see the CPP gui package
  11.  **************************************************************/
  12.  
  13. #define MSDOS 1
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include "display.h"
  20. #include "gui.h"
  21. #include "loadsave.h"
  22. #include "zone.h"
  23.  
  24.  
  25. /* exit values */
  26. #define EXIT_OK 0
  27. #define EXIT_NO_GRAPHICS 1
  28.  
  29. /* graphics format types */
  30. #define AUTO 0
  31. #define CCITT4 1
  32. #define CCITT3 2
  33. #define PCX 3
  34. #define TIFF 4
  35. #define GIF 5
  36. #define BMP 6
  37.  
  38. /* local data */
  39. static char dir_search[FILENAME_MAX+1] = ".\\*.pcx";
  40. static char file_choice[FILENAME_MAX+1];
  41. static short format_open = PCX;
  42. static short format_save = CCITT4;
  43. static short density_value = 2;
  44. static short zones_displayed = 0;
  45.  
  46.  
  47. /* local prototypes */
  48. static short dispatch_message(MESSAGE *message);
  49. static short dialog_format_handler(short dialog_type);
  50. static short dialog_number_handler(short *current,short minimum,short maximum,short dx,short dy);
  51. static void draw_slider(short value,short minimum,short maximum);
  52. static short dialog_help_handler(void);
  53.  
  54.  
  55. /* menu bar data */
  56. /* menu ids */
  57. #define M_FILE 300
  58. #define M_FILE_OPEN 301
  59. #define M_EDIT 400
  60. #define M_ZONE 401
  61. #define M_OPTIONS 500
  62. #define M_SETDENSITY 501
  63. #define M_ORDER 502
  64. #define M_HELP 600
  65.  
  66. /* menu components */
  67. static POPUP_ITEM file_popup[] =
  68.     {
  69.     {M_FILE_OPEN,"Open   Ctrl+O",CTRLO,MENU_ACTIVE},
  70.     {M_QUIT,"Quit   Ctrl+Q",CTRLQ,MENU_ACTIVE}
  71.     };
  72. #define SHOW_MENU_POSITION 0
  73. static POPUP_ITEM edit_popup[] =
  74.     {
  75.     {M_ZONE,"Show Zones    Ctrl+Z",CTRLZ,MENU_GRAY}
  76.     };
  77. static char row_order[] = "Row Major Order     Ctrl+T";
  78. static char column_order[] = "Column Major Order  Ctrl+T";
  79. #define ORDER_MENU_POSITION 1
  80. static POPUP_ITEM option_popup[] =
  81.     {
  82.     {M_SETDENSITY,"Set Zone Density    Ctrl+D",CTRLD,MENU_ACTIVE},
  83.     {M_ORDER,column_order,CTRLT,MENU_ACTIVE}
  84.     };
  85. static MENU_ITEM menubar[] =
  86.     {
  87.     {M_FILE,"&File",ALTF,&file_popup[0],sizeof(file_popup)/sizeof(POPUP_ITEM),MENU_ACTIVE},
  88.     {M_OPTIONS,"&Edit",ALTE,&edit_popup[0],sizeof(edit_popup)/sizeof(POPUP_ITEM),MENU_ACTIVE},
  89.     {M_OPTIONS,"&Options",ALTO,&option_popup[0],sizeof(option_popup)/sizeof(POPUP_ITEM),MENU_ACTIVE},
  90.     {M_HELP,"&Help",ALTH,NULL,0,MENU_ACTIVE}
  91.     };
  92.  
  93. /* format button and dialog */
  94. #define D_FORMAT_OPEN 1000
  95. static BUTTON format_button_open = {D_FORMAT_OPEN,"&Format",ALTF,0,0,DIALOG_ACTIVE};
  96. #define D_FORMAT_SAVE 1001
  97. static BUTTON format_button_save = {D_FORMAT_SAVE,"&Format",ALTF,0,0,DIALOG_ACTIVE};
  98. #define D_FORMAT_WIDTH (16*DIALOG_UNITS)
  99. #define D_FORMAT_HEIGHT (11*DIALOG_UNITS)
  100. #define D_FORMAT_RADIOBUTTON 1100
  101. #define D_FORMAT_MIN_TYPE 1101      /* the following sequence must track the graphic format types */
  102. #define D_FORMAT_AUTO 1101
  103. #define D_FORMAT_CCITT4 1102
  104. #define D_FORMAT_CCITT3 1103
  105. #define D_FORMAT_PCX 1104
  106. #define D_FORMAT_TIFF 1105
  107. #define D_FORMAT_GIF 1106
  108. #define D_FORMAT_BMP 1107
  109. #define D_FORMAT_MAX_TYPE 1199      /* end of format type sequence */
  110. #define D_FORMAT_OK 1200
  111. #define D_FORMAT_CANCEL 1300
  112. static BUTTON format_choices[] =
  113.     {
  114.     {D_FORMAT_AUTO,"Auto",ALT1,4*DIALOG_UNITS,9*DIALOG_UNITS,DIALOG_GRAY},
  115.     {D_FORMAT_CCITT4,"CCITT4",ALT2,4*DIALOG_UNITS,8*DIALOG_UNITS,DIALOG_GRAY},
  116.     {D_FORMAT_CCITT3,"CCITT3",ALT3,4*DIALOG_UNITS,7*DIALOG_UNITS,DIALOG_GRAY},
  117.     {D_FORMAT_PCX,"PCX",ALT4,4*DIALOG_UNITS,6*DIALOG_UNITS,DIALOG_ACTIVE|DIALOG_SELECTED},
  118.     {D_FORMAT_TIFF,"TIFF",ALT5,4*DIALOG_UNITS,5*DIALOG_UNITS,DIALOG_GRAY},
  119.     {D_FORMAT_GIF,"GIF",ALT6,4*DIALOG_UNITS,4*DIALOG_UNITS,DIALOG_GRAY},
  120.     {D_FORMAT_BMP,"BMP",ALT7,4*DIALOG_UNITS,3*DIALOG_UNITS,DIALOG_GRAY}
  121.     };
  122. static RADIOBUTTON format_radiobutton = {D_FORMAT_RADIOBUTTON,sizeof(format_choices)/sizeof(BUTTON),format_choices,DIALOG_ACTIVE};
  123. static BUTTON format_cancel = {D_FORMAT_CANCEL,"Cancel",ESC,2*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  124. static BUTTON format_ok = {D_FORMAT_OK,"Ok",F10,D_FORMAT_WIDTH-4*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  125. static DIALOG_ITEM dialog_format[] =
  126.     {
  127.     {DIALOG_RADIOBUTTON,&format_radiobutton},
  128.     {DIALOG_BUTTON,&format_cancel},
  129.     {DIALOG_BUTTON,&format_ok}
  130.     };
  131.  
  132.  
  133. /* number dialog */
  134. #define D_NUMBER_WIDTH 33 * DIALOG_UNITS
  135. #define D_NUMBER_HEIGHT 8 * DIALOG_UNITS
  136. #define NUMBER_EDIT_WIDTH 4
  137. #define D_NUMBER 2000
  138. #define D_NUMBER_OK 2001
  139. #define D_NUMBER_CANCEL 2002
  140. #define D_NUMBER_EDIT 2003
  141. #define D_NUMBER_SLIDER 2004
  142. #define D_NUMBER_LEFT 2005
  143. #define D_NUMBER_RIGHT 2006
  144. static char number_str[NUMBER_EDIT_WIDTH+1];
  145. static TEXT number_title = {"Enter a new zone density:",1*DIALOG_UNITS,6*DIALOG_UNITS,DIALOG_ACTIVE};
  146. static EDITBOX number_edit = {D_NUMBER_EDIT,27*DIALOG_UNITS,6*DIALOG_UNITS,NUMBER_EDIT_WIDTH*DIALOG_UNITS,NUMBER_EDIT_WIDTH,number_str,DIALOG_ACTIVE};
  147. static TEXT number_min = {"0",8*DIALOG_UNITS+DIALOG_UNITS/2,4*DIALOG_UNITS,DIALOG_ACTIVE};
  148. static BUTTON number_slider = {D_NUMBER_SLIDER,"          ",0,11*DIALOG_UNITS+DIALOG_UNITS/2,4*DIALOG_UNITS,DIALOG_GRAY};
  149. static TEXT number_max = {"5",23*DIALOG_UNITS+DIALOG_UNITS/2,4*DIALOG_UNITS,DIALOG_ACTIVE};
  150. static BUTTON number_left = {D_NUMBER_LEFT,"<<",'-',13*DIALOG_UNITS,2*DIALOG_UNITS,DIALOG_ACTIVE};
  151. static BUTTON number_right = {D_NUMBER_RIGHT,">>",'+',18*DIALOG_UNITS,2*DIALOG_UNITS,DIALOG_ACTIVE};
  152. static BUTTON number_cancel = {D_NUMBER_CANCEL,"Cancel",ESC,2*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  153. static BUTTON number_ok = {D_NUMBER_OK,"Ok",F10,D_NUMBER_WIDTH-4*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  154. static DIALOG_ITEM dialog_number[] =
  155.     {
  156.     {DIALOG_TEXT,&number_title},
  157.     {DIALOG_EDITBOX,&number_edit},
  158.     {DIALOG_TEXT,&number_min},
  159.     {DIALOG_BUTTON,&number_slider},
  160.     {DIALOG_TEXT,&number_max},
  161.     {DIALOG_BUTTON,&number_left},
  162.     {DIALOG_BUTTON,&number_right},
  163.     {DIALOG_BUTTON,&number_cancel},
  164.     {DIALOG_BUTTON,&number_ok}
  165.     };
  166.  
  167.  
  168. /* help dialog */
  169. #define D_HELP_WIDTH (50*DIALOG_UNITS)
  170. #define D_HELP_HEIGHT (13*DIALOG_UNITS)
  171. #define D_HELP_OK 3000
  172. static TEXT help1 = {"This program demonstrates region detection on",1*DIALOG_UNITS,12*DIALOG_UNITS,DIALOG_ACTIVE};
  173. static TEXT help2 = {"text pages using cellular automata.  Follow",1*DIALOG_UNITS,11*DIALOG_UNITS,DIALOG_ACTIVE};
  174. static TEXT help3 = {"these steps:",1*DIALOG_UNITS,10*DIALOG_UNITS,DIALOG_ACTIVE};
  175. static TEXT help4 = {"1) Open a monochrome PCX file (File/Open).",1*DIALOG_UNITS,9*DIALOG_UNITS,DIALOG_ACTIVE};
  176. static TEXT help5 = {"2) Display the regions (Edit/Show).",1*DIALOG_UNITS,8*DIALOG_UNITS,DIALOG_ACTIVE};
  177. static TEXT help6 = {"3) Change the zone density (Option/Density)",1*DIALOG_UNITS,7*DIALOG_UNITS,DIALOG_ACTIVE};
  178. static TEXT help7 = {"4) or change the ordering (Option/Order)",1*DIALOG_UNITS,6*DIALOG_UNITS,DIALOG_ACTIVE};
  179. static TEXT help8 = {"and redisplay (Edit/Show) to see their effects.",1*DIALOG_UNITS,5*DIALOG_UNITS,DIALOG_ACTIVE};
  180. static TEXT help9 = {"1993 - David Weber, Box 1376 Paonia CO 81428",1*DIALOG_UNITS,3*DIALOG_UNITS,DIALOG_ACTIVE};
  181. static BUTTON help_ok = {D_HELP_OK,"Ok",ESC,24*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  182. static DIALOG_ITEM dialog_help[] =
  183.     {
  184.     {DIALOG_TEXT,&help1},
  185.     {DIALOG_TEXT,&help2},
  186.     {DIALOG_TEXT,&help3},
  187.     {DIALOG_TEXT,&help4},
  188.     {DIALOG_TEXT,&help5},
  189.     {DIALOG_TEXT,&help6},
  190.     {DIALOG_TEXT,&help7},
  191.     {DIALOG_TEXT,&help8},
  192.     {DIALOG_TEXT,&help9},
  193.     {DIALOG_BUTTON,&help_ok}
  194.     };
  195.  
  196.  
  197.  
  198.  
  199. /* wherein all things commence */
  200. short main()
  201.     {
  202.     MESSAGE message;
  203.  
  204.     if (!gui_open())        /* fire up the graphics */
  205.         {
  206.         printf("Cannot initialize graphics display\n");
  207.         exit(EXIT_NO_GRAPHICS);
  208.         }
  209.     do                      /* loop on message stream */
  210.         {
  211.         if (message_get(&message) == M_QUIT)
  212.             if (yn_box("Are you sure"))
  213.                 break;
  214.         } while (dispatch_message(&message));
  215.     display_free();         /* close down shop */
  216.     gui_close();
  217.     return EXIT_OK;
  218.     }
  219.  
  220.  
  221. /* process messages, returns 1 if OK and 0 if fatal failure */
  222. static short dispatch_message(MESSAGE *message)
  223.     {
  224.     short order;
  225.  
  226.     switch (message->id)
  227.         {
  228.         case M_START:           /* put up menu on start up */
  229.             if (!menu_open(menubar,sizeof(menubar)/sizeof(MENU_ITEM)))
  230.                 {
  231.                 error_box(gui_errno);
  232.                 return 0;
  233.                 }
  234.             break;
  235.         case M_FILE_OPEN:       /* open file and display it */
  236.             loadsave_add_button(&format_button_open,dispatch_message);
  237.             if (loadsave(dir_search,file_choice,LOADSAVE_LOAD | LOADSAVE_VERIFY))
  238.                 {
  239.                 menu_clear(menubar);
  240.                 if (display_file(file_choice))
  241.                     {           /* activate zoning menu options */
  242.                     edit_popup[SHOW_MENU_POSITION].status = MENU_ACTIVE;
  243.                     }
  244.                 else
  245.                     {           /* clear zoning menu options */
  246.                     edit_popup[SHOW_MENU_POSITION].status = MENU_GRAY;
  247.                     }
  248.                 zones_displayed = 0;
  249.                 }
  250.             break;
  251.         case D_FORMAT_OPEN:     /* get user format selection */
  252.             return dialog_format_handler(D_FORMAT_OPEN);
  253.         case M_ZONE:
  254.             if (option_popup[ORDER_MENU_POSITION].name == column_order)
  255.                 order = COLUMN_MAJOR;
  256.             else
  257.                 order = ROW_MAJOR;
  258.             if (!zone(density_value,order))
  259.                 {
  260.                 message_box("Out of Memory.");
  261.                 break;
  262.                 }
  263.             menu_clear(menubar);
  264.             if (zones_displayed)
  265.                 display_redraw();
  266.             display_zones();
  267.             zones_displayed = 1;
  268.             break;
  269.         case M_SETDENSITY:
  270.             dialog_number_handler(&density_value,0,5,-1,-1);
  271.             break;
  272.         case M_ORDER:
  273.             if (option_popup[ORDER_MENU_POSITION].name == column_order)
  274.                 option_popup[ORDER_MENU_POSITION].name = row_order;
  275.             else
  276.                 option_popup[ORDER_MENU_POSITION].name = column_order;
  277.             menu_modify(menubar,M_ORDER,MENU_ACTIVE);
  278.             break;
  279.         case M_HELP:
  280.             dialog_help_handler();
  281.             break;
  282.         default:                /* show possible error */
  283.             error_box(message->id);
  284.             break;
  285.         }
  286.     return 1;
  287.     }
  288.  
  289.  
  290. /* handle the format dialog, returns 1 if OK or 0 if failure */
  291. static short dialog_format_handler(short dialog_type)
  292.     {
  293.     MESSAGE message;
  294.     short temp_format,*format_storage,dx,dy;
  295.  
  296.     dx = dy = -1;
  297.     if (dialog_type == D_FORMAT_SAVE)   /* remove AUTO button for save */
  298.         {
  299.         format_storage = &format_save;
  300.         dialog_status_set(format_choices[0],DIALOG_INACTIVE);
  301.         loadsave_button_location(&format_button_save,&dx,&dy);
  302.         }
  303.     else                                /* replace AUTO button for open */
  304.         {
  305.         format_storage = &format_open;
  306.         dialog_status_set(format_choices[0],DIALOG_GRAY);
  307.         loadsave_button_location(&format_button_open,&dx,&dy);
  308.         }
  309.     if (dx >= 0 && dy >= 0)             /* orient new dialog box */
  310.         {
  311.         dy -= D_FORMAT_HEIGHT;
  312.         if (dy < 0)
  313.             dy = 0;
  314.         }
  315.     radiobutton_set(&format_radiobutton,*format_storage+D_FORMAT_MIN_TYPE);
  316.     if (!dialog_open(dialog_format,sizeof(dialog_format)/sizeof(DIALOG_ITEM),dx,dy,D_FORMAT_WIDTH,D_FORMAT_HEIGHT))
  317.         return 0;
  318.     temp_format = *format_storage;
  319.     for (;;)
  320.         {
  321.         message_get(&message);
  322.         switch(message.id)
  323.             {
  324.             case D_FORMAT_OK:           /* save format choice */
  325.                 *format_storage = temp_format;
  326.                 dialog_close(dialog_format);
  327.                 return 1;
  328.             case D_FORMAT_CANCEL:       /* reject format choice */
  329.                 dialog_close(dialog_format);
  330.                 radiobutton_set(&format_radiobutton,*format_storage+D_FORMAT_MIN_TYPE);
  331.                 return 1;
  332.             case D_FORMAT_RADIOBUTTON:  /* select format choice */
  333.                 temp_format = message.data.short_data.x - D_FORMAT_MIN_TYPE;
  334.                 break;
  335.             default:
  336.                 if (error_box(message.id))      /* check if error */
  337.                     {
  338.                     dialog_close(dialog_format);
  339.                     return 0;
  340.                     }
  341.                 break;
  342.             }
  343.         }
  344.     }
  345.  
  346.  
  347. /* get a new number into value, returns 1 if OK or 0 if failure */
  348. static short dialog_number_handler(short *current,short minimum,short maximum,short dx,short dy)
  349.     {
  350.     MESSAGE message;
  351.     short temp;
  352.  
  353.     temp = *current;
  354.     sprintf(number_str,"%d",temp);
  355.     if (!dialog_open(dialog_number,sizeof(dialog_number)/sizeof(DIALOG_ITEM),dx,dy,D_NUMBER_WIDTH,D_NUMBER_HEIGHT))
  356.         return 0;
  357.     draw_slider(temp,minimum,maximum);
  358.     for (;;)
  359.         {
  360.         message_get(&message);
  361.         switch(message.id)
  362.             {
  363.             case D_NUMBER_CANCEL:       /* reject changes */
  364.                 dialog_close(dialog_number);
  365.                 return 1;
  366.             case D_NUMBER_OK:           /* save new number, fall through */
  367.             case D_NUMBER_EDIT:         /* edit value */
  368.                 temp = atoi(number_str);
  369.                 if (message.id == D_NUMBER_EDIT && message.data.short_data.x != EDITBOX_ACCEPT)
  370.                     {
  371.                     if (temp > maximum)
  372.                         temp = maximum;
  373.                     else if (!isdigit(*number_str) || temp < minimum)
  374.                         temp = minimum;
  375.                     draw_slider(temp,minimum,maximum);
  376.                     break;
  377.                     }
  378.                 if (temp < minimum || temp > maximum || !isdigit(*number_str))
  379.                     {
  380.                     message_box("Invalid Number");
  381.                     temp = *current;
  382.                     sprintf(number_str,"%d",temp);
  383.                     editbox_initialize(&number_edit);
  384.                     draw_slider(temp,minimum,maximum);
  385.                     break;
  386.                     }
  387.                 *current = temp;
  388.                 dialog_close(dialog_number);
  389.                 return 1;
  390.             case D_NUMBER_LEFT:                 /* click slider left */
  391.                 temp--;
  392.                 if (temp < minimum)
  393.                     temp = maximum;
  394.                 sprintf(number_str,"%d",temp);
  395.                 editbox_initialize(&number_edit);
  396.                 draw_slider(temp,minimum,maximum);
  397.                 break;
  398.             case D_NUMBER_RIGHT:                /* click slider right */
  399.                 temp++;
  400.                 if (temp > maximum)
  401.                     temp = minimum;
  402.                 sprintf(number_str,"%d",temp);
  403.                 editbox_initialize(&number_edit);
  404.                 draw_slider(temp,minimum,maximum);
  405.                 break;
  406.             default:
  407.                 if (error_box(message.id))      /* check if error */
  408.                     {
  409.                     dialog_close(dialog_number);
  410.                     return 0;
  411.                     }
  412.                 break;
  413.             }
  414.         }
  415.     }
  416.  
  417.  
  418. /* draw the slider on the number_dialog */
  419. static short empty_character = 176;
  420. static short full_character = 219;
  421. static void draw_slider(short value,short minimum,short maximum)
  422.     {
  423.     char *p;
  424.     short len,cell_height;
  425.     fg_box_t box;
  426.  
  427.     if (fg.fontptr2 == (char _far *) NULL)
  428.         {   /* CGA has bogus characters 128-255 */
  429.         empty_character = '-';
  430.         full_character = '#';
  431.         }
  432.     p = number_slider.name;
  433.     len = strlen(p);
  434.     cell_height = gui_char_height + 6;
  435.     if (gui_char_height + gui_char_height/2 > cell_height)
  436.         cell_height = gui_char_height + gui_char_height/2;
  437.     fg_msm_hidecursor();
  438.     fg_box_cpy(box,number_slider.screen);
  439.     box[FG_X1] += gui_char_width;
  440.     box[FG_Y1] += (cell_height-gui_char_height)/2;
  441.     box[FG_X2] -= gui_char_width;
  442.     box[FG_Y2] = box[FG_Y1] + gui_char_height;
  443.     fg_fillbox(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,box);
  444.     value = (value*len)/(maximum-minimum) + minimum;
  445.     memset(p,empty_character,len);
  446.     memset(p,full_character,value);
  447.     fg_puts(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_ROT0,box[FG_X1],box[FG_Y1],p,number_slider.screen);
  448.     fg_msm_showcursor();
  449.     fg_flush();
  450.     }
  451.  
  452.  
  453. /* handle the help dialog */
  454. static short dialog_help_handler(void)
  455.     {
  456.     MESSAGE message;
  457.  
  458.     if (!dialog_open(dialog_help,sizeof(dialog_help)/sizeof(DIALOG_ITEM),-1,-1,D_HELP_WIDTH,D_HELP_HEIGHT))
  459.         return 0;
  460.     for (;;)
  461.         {
  462.         message_get(&message);
  463.         if (message.id == D_HELP_OK)
  464.             break;
  465.         }
  466.     dialog_close(dialog_help);
  467.     return 1;
  468.     }
  469.