home *** CD-ROM | disk | FTP | other *** search
/ Multi-CD Magazin 1994 April / MultiCDMagazin0494.iso01.iso / sharew / font / fontprn / source / enumfont.c < prev    next >
Text File  |  1993-03-16  |  40KB  |  1,210 lines

  1. // Contents copyright (c) 1993 John Deurbrouck
  2. /*
  3. **  Define DEBUG for compilation under Borland C++ 3.1 to get a
  4. **  standalone test version of ENUMFONT.C
  5. */
  6. #ifdef DEBUG
  7. int wanna_quit=0;
  8. #endif
  9.  
  10. /*
  11. **  Includes
  12. */
  13. #include<windows.h>
  14. #include<stdio.h>
  15. #include<stdlib.h>
  16. #include<stdarg.h>
  17. #include<commdlg.h>
  18. #include<string.h>
  19. #include"enumfont.h"
  20.  
  21. /*
  22. **  Private Defines
  23. */
  24. #ifdef DEBUG
  25.     #define printf mprintf
  26. #endif
  27. #define FONTHASREGULAR      1
  28. #define FONTHASBOLD         2
  29. #define FONTHASITALIC       4
  30. #define FONTHASBOLDITALIC   8
  31. #define FONTISTRUETYPE     16
  32. #define FONTISFIXEDWIDTH   32
  33. #define MAXALLOCATIONS    100
  34. #define ALLOCATIONSIZE  32000
  35. #define MAXFONTS          512
  36.  
  37. /*
  38. **  Type Definitions
  39. */
  40. // TRACKFONT struct used to store font data
  41. typedef struct tagTRACKFONT{
  42.     LPSTR facename;
  43.     int flags;
  44.     int height;
  45.     int width;
  46.     int narrowness;
  47.     int weight;
  48.     BYTE fonttype;
  49.     LPSTR regular,bold,italic,bolditalic;
  50. }TRACKFONT,FAR* LPTRACKFONT;
  51. // TEXTQUEUE for linked list of .WRI file data
  52. typedef struct tagTEXTQUEUE{
  53.     LPSTR text;
  54.     int textlen;
  55.     void FAR* next;
  56. }TEXTQUEUE,FAR* LPTEXTQUEUE;
  57. // WRITEFILEHEADER used to write .WRI header
  58. typedef struct tagWRITEFILEHEADER{
  59.     int wIdent;
  60.     int dty;
  61.     int wTool;
  62.     int wReserved[4];
  63.     long fcMac;
  64.     int pnPara;
  65.     int pnFntb;
  66.     int pnSep;
  67.     int pnSetb;
  68.     int pnPgtb;
  69.     int pnFfntb;
  70.     int szSsht[33];
  71.     int pnMac;
  72.     int wReserved2[15];
  73. }WRITEFILEHEADER,FAR* LPWRITEFILEHEADER;
  74. // FOD for .WRI file generation
  75. typedef struct tagFOD{
  76.     long fcLim;
  77.     int bfprop;
  78. }FOD,FAR* LPFOD;
  79. // PAP for .WRI file paragraph data
  80. typedef struct tagPAP{
  81.     char len;
  82.     char res1;
  83.     char just;
  84. }PAP,FAR* LPPAP;
  85. // CHP3, CHP5 for .WRI file character information
  86. typedef struct tagCHP3{
  87.     char len;
  88.     char res1;
  89.     unsigned char bold_it_fontLSBs;
  90.     char fontsiz;
  91. }CHP3,FAR* LPCHP3;
  92. typedef struct tagCHP5{
  93.     char len;
  94.     char res1;
  95.     unsigned char bold_it_fontLSBs;
  96.     char fontsiz;
  97.     char uline;
  98.     unsigned char fontMSBs;
  99. }CHP5,FAR* LPCHP5;
  100.  
  101. /*
  102. **  Global Variables
  103. */
  104. HANDLE instance=0;
  105. HWND hwndSortorder;
  106. HWND hwndDialog;
  107. /* following are user choices to drive file generation */
  108. SORTORDER sortorder=ALPHA;
  109. MONOSPACE monospace=VARMONO;
  110. int use_printer_context=0,allow_synthesis=0,truetype_only=0;
  111. int incl_novelty=0,incl_modern=0,incl_roman=0,
  112.    incl_script=0,incl_sanserif=0,incl_other=0;
  113. int incl_regular=0,incl_bold=0,incl_italic=0,incl_bolditalic=0;
  114. int launchwrite=0;
  115. /* following are for internal use of generate_file_from_options() */
  116. static int successful_so_far,did_bailout;// error-occurred variable
  117. static OPENFILENAME ofn;
  118. static HFILE file=HFILE_ERROR;
  119. static int fams;                        // font families in fonts
  120. static LPTRACKFONT fonts[MAXFONTS];
  121. static HDC hdc;
  122. static FONTENUMPROC do_families,do_individuals;
  123. /* following are for use of get_memory() and free_memory() */
  124. static HGLOBAL mem_handles[MAXALLOCATIONS];
  125. static int mem_handles_used=0,memory_system_restart=0;
  126. // following set by dialog proc, used by generate_file_from_options()
  127. LPSTR sample_text_ptr=0;
  128. int sample_text_length=0;
  129. int sample_text_pointsize=0;       // in half-points (24==12pt)
  130. int sample_text_just=0;            // JUST_LEFT ... JUST_JUST
  131. LPSTR default_font=0;
  132. BYTE default_ffid=0;
  133. int default_pointsize=0;           // in half-points (24==12 pt)
  134. int default_just=0;                // JUST_LEFT ... JUST_JUST
  135. int default_bolditalic=0;          // BOLD_BIT | ITALIC_BIT
  136. // generate_file_from_options() sets and uses for .WRI file:
  137. LPTEXTQUEUE text_first,text_last;
  138. LPTEXTQUEUE char_first,char_last;
  139. LPTEXTQUEUE graf_first,graf_last;
  140. LPTEXTQUEUE font_first,font_last;
  141. long text_bytes,char_pages,graf_pages,font_pages;
  142. int default_font_offset;                // font code for default txt
  143.  
  144. /*
  145. **  Function Prototypes
  146. */
  147. int PASCAL WinMain(HANDLE hInstance,HANDLE hPrevInst,LPSTR cmd,int Show);
  148. static void bailout(char *msg);
  149. int CALLBACK _export families(LPENUMLOGFONT lpelf,TEXTMETRIC FAR* tmptr,
  150.     int fonttype,LPARAM lparam);
  151. static LPSTR get_font_type(BYTE pitchandfamily);
  152. int CALLBACK _export individuals(LPENUMLOGFONT lpelf,TEXTMETRIC FAR* tmptr,
  153.     int fonttype,LPARAM lparam);
  154. #ifdef DEBUG
  155. int mprintf(const char *fmt,...);
  156. #endif
  157. static void open_output_file(void);
  158. static void gather_data(void);
  159. static void sort_data(void);
  160. static int sorter(const void* arg1,const void* arg2);
  161. static void FAR* get_zeroed_memory(size_t size);
  162. static void FAR* get_memory(size_t size);
  163. static void free_memory(void);
  164. static void generate_report(void);
  165. static void w_init(void);
  166. static void w_default(const char* fmt,...);
  167. static void w_sample(LPTRACKFONT lpf,int bolditalic);
  168. static int w_add_font(LPSTR name, BYTE ffid);
  169. static void w_add_graf(int textlen,int just);
  170. static void w_add_char(int textlen,int bolditalic,int fontcode,int size);
  171. static void w_add_text(LPSTR text,int size);
  172. static void write_data_file(void);
  173. static int write_data_chunk(LPSTR buf,size_t buflen);
  174. static void create_device_context(void);
  175. static void get_user_options(void);
  176.  
  177. /*
  178. **  Function Definitions
  179. */
  180. #ifdef DEBUG
  181. #pragma argsused
  182. // test scaffolding
  183. int PASCAL WinMain(HANDLE hInstance,HANDLE hPrevInst,LPSTR cmd,int Show){
  184.     _InitEasyWin();
  185.     instance=hInstance;
  186.     for(;;){
  187.         get_user_options();
  188.         if(wanna_quit)break;
  189.         generate_file_from_options();
  190.     }
  191.     return 0;
  192. }
  193. #endif
  194.  
  195. void generate_file_from_options(void){
  196.     // initialize global variables
  197.     do_families=do_individuals=NULL;
  198.     hdc=NULL;
  199.     successful_so_far=1;
  200.     did_bailout=0;
  201.     fams=0;
  202.     // ok, let's get to work
  203.     if(successful_so_far)gather_data();
  204.     if(successful_so_far)sort_data();
  205.     if(successful_so_far)generate_report();
  206.     if(successful_so_far)open_output_file();
  207.     if(successful_so_far)write_data_file();
  208.     if(successful_so_far)bailout(NULL);
  209.     else SetFocus(hwndSortorder);
  210. }
  211.  
  212. // clean up, release memory, device context, etc.
  213. static void bailout(char *msg){
  214.     if(did_bailout)return;              // don't do this stuff twice
  215.     if(msg!=NULL){
  216.         MessageBox(hwndDialog,msg,"Error",MB_OK|MB_ICONEXCLAMATION);
  217.         successful_so_far=0;
  218.     }
  219.     if(hdc!=NULL){
  220.         DeleteDC(hdc);
  221.         hdc=NULL;
  222.     }
  223.     if(do_families!=NULL){
  224.         FreeProcInstance(do_families);
  225.         do_families=NULL;
  226.     }
  227.     if(do_individuals!=NULL){
  228.         FreeProcInstance(do_individuals);
  229.         do_individuals=NULL;
  230.     }
  231.     if(file!=HFILE_ERROR){
  232.         char buf[270];
  233.         _lclose(file);
  234.         file=HFILE_ERROR;
  235.         if(launchwrite&&successful_so_far){
  236.             wsprintf(buf,"WRITE %s",ofn.lpstrFile);
  237.             SetFocus(hwndSortorder);
  238.             WinExec(buf,SW_SHOWNORMAL);
  239.         }
  240.     }
  241.     free_memory();
  242. }
  243.  
  244. // families() is the callback function passed to EnumFontFamilies()
  245. // it's called for every font family. for each family of interest,
  246. // families() calls EnumFontFamilies() with individuals() as the
  247. // callback function. this gathers information on presence of
  248. // bold, italic, etc. and puts it into fonts[]
  249. #pragma argsused
  250. int CALLBACK _export families(LPENUMLOGFONT lpelf,TEXTMETRIC FAR* tmptr,
  251.     int fonttype,LPARAM lparam){
  252.     if(fams==MAXFONTS){
  253.         // only nine bits available for font number, so .WRI file
  254.         // can't have more than 512 fonts
  255.         MessageBox(hwndDialog,"Due to limitations in the .WRI format, "
  256.         "only working with first 512 font families.\n\n"
  257.         "Assemble several reports to list all your fonts.",
  258.             "Too many fonts",MB_OK|MB_ICONINFORMATION);
  259.         return 0;
  260.     }
  261.     // if we don't want non-TT, don't gather this one...
  262.     if(truetype_only&&!(fonttype&TRUETYPE_FONTTYPE))return 1;
  263.     // if we don't want this font type, don't gather it...
  264.     switch(lpelf->elfLogFont.lfPitchAndFamily&~3){
  265.     case FF_DECORATIVE: if(!incl_novelty)return 1;  break;
  266.     case FF_MODERN:     if(!incl_modern)return 1;   break;
  267.     case FF_ROMAN:      if(!incl_roman)return 1;    break;
  268.     case FF_SCRIPT:     if(!incl_script)return 1;   break;
  269.     case FF_SWISS:      if(!incl_sanserif)return 1; break;
  270.     default:            if(!incl_other)return 1;    break;
  271.     }
  272.     // if monospace preference, check it
  273.    if(monospace!=VARMONO){
  274.         if(lpelf->elfLogFont.lfPitchAndFamily&FIXED_PITCH){
  275.             if(monospace==VAR)return 1; // unwanted fixed pitch
  276.         }
  277.         else{
  278.             if(monospace==MONO)return 1;// unwanted var pitch
  279.         }
  280.     }
  281.     // get space and save family information
  282.     fonts[fams]=get_memory(sizeof(TRACKFONT));
  283.     if(!successful_so_far)return 0;
  284.     fonts[fams]->facename=
  285.         get_memory(lstrlen(lpelf->elfLogFont.lfFaceName)+1);
  286.     if(!successful_so_far)return 0;
  287.     lstrcpy(fonts[fams]->facename,lpelf->elfLogFont.lfFaceName);
  288.     fonts[fams]->flags=fonttype&TRUETYPE_FONTTYPE?FONTISTRUETYPE:0;
  289.     if(lpelf->elfLogFont.lfPitchAndFamily&FIXED_PITCH)
  290.         fonts[fams]->flags|=FONTISFIXEDWIDTH;
  291.     fonts[fams]->fonttype=lpelf->elfLogFont.lfPitchAndFamily&~3;
  292.     // set high value for following; individuals will write in if smaller
  293.     fonts[fams]->height=fonts[fams]->width=fonts[fams]->weight=30000;
  294.     // set extra style name pointers to NULL
  295.     fonts[fams]->regular=fonts[fams]->bold=
  296.         fonts[fams]->italic=fonts[fams]->bolditalic=NULL;
  297.     // collect the data...
  298.     EnumFontFamilies(hdc,lpelf->elfLogFont.lfFaceName,do_individuals,NULL);
  299.     // compute narrowness...
  300.     if(!successful_so_far)return 0;
  301.     fonts[fams]->narrowness=fonts[fams]->width<1?0:
  302.         (int)(((float)fonts[fams]->height/(float)fonts[fams]->width)*10.0);
  303.     // if allowed, set synthesized style bits, style name pointers
  304.     if(allow_synthesis){
  305.         if(fonts[fams]->flags&FONTHASREGULAR){
  306.             if(!(fonts[fams]->flags&FONTHASBOLD)){
  307.                 fonts[fams]->flags|=FONTHASBOLD;
  308.                 fonts[fams]->bold="Synthesized Bold";
  309.             }
  310.             if(!(fonts[fams]->flags&FONTHASITALIC)){
  311.                 fonts[fams]->flags|=FONTHASITALIC;
  312.                 fonts[fams]->italic="Synthesized Italic";
  313.             }
  314.         }
  315.         if(fonts[fams]->flags&FONTHASREGULAR||
  316.         fonts[fams]->flags&FONTHASBOLD||
  317.         fonts[fams]->flags&FONTHASITALIC){
  318.             if(!(fonts[fams]->flags&FONTHASBOLDITALIC)){
  319.                 fonts[fams]->flags|=FONTHASBOLDITALIC;
  320.                 fonts[fams]->bolditalic="Synthesized Bold Italic";
  321.             }
  322.         }
  323.     }
  324.     // zero out undesired style-present bits
  325.     if(!incl_regular)   fonts[fams]->flags&=~FONTHASREGULAR;
  326.     if(!incl_bold)      fonts[fams]->flags&=~FONTHASBOLD;
  327.     if(!incl_italic)    fonts[fams]->flags&=~FONTHASITALIC;
  328.     if(!incl_bolditalic)fonts[fams]->flags&=~FONTHASBOLDITALIC;
  329.     // only increment fams if a desired style bit is set
  330.     // sure, a little memory is wasted but we'll give it back soon...
  331.     if(fonts[fams]->flags&FONTHASREGULAR||
  332.     fonts[fams]->flags&FONTHASBOLD||
  333.     fonts[fams]->flags&FONTHASITALIC||
  334.     fonts[fams]->flags&FONTHASBOLDITALIC)
  335.         fams++;
  336.     return 1;
  337. }
  338.  
  339. static LPSTR get_font_type(BYTE pitchandfamily){
  340.     switch(pitchandfamily&~3){
  341.     case FF_DECORATIVE:     return "novelty";
  342.     case FF_MODERN:         return "modern";
  343.     case FF_ROMAN:          return "Roman";
  344.     case FF_SCRIPT:         return "script";
  345.     case FF_SWISS:          return "sans serif";
  346.     default:                return "unknown";
  347.     }
  348. }
  349.  
  350. // callback function for EnumFontFamilies()
  351. // called once for each font style in a font (bold, italic, etc.)
  352. // stores information into fonts[]
  353. #pragma argsused
  354. int CALLBACK _export individuals(LPENUMLOGFONT lpelf,TEXTMETRIC FAR* tmptr,
  355.     int fonttype,LPARAM lparam){
  356.     LPSTR lpstr=NULL;
  357.     int truetype=0;
  358.     if(!successful_so_far)return 0;
  359.     // collect min height, width, weight
  360.     if(fonts[fams]->height>lpelf->elfLogFont.lfHeight)
  361.         fonts[fams]->height=lpelf->elfLogFont.lfHeight;
  362.     if(fonts[fams]->width>lpelf->elfLogFont.lfWidth)
  363.         fonts[fams]->width=lpelf->elfLogFont.lfWidth;
  364.     if(fonts[fams]->weight>lpelf->elfLogFont.lfWeight)
  365.         fonts[fams]->weight=lpelf->elfLogFont.lfWeight;
  366.     if(fonts[fams]->flags&FONTISTRUETYPE)truetype=1;
  367.     while(truetype){
  368.         if(lpelf->elfStyle==NULL)break;
  369.         if(lstrlen(lpelf->elfStyle)<1)break;
  370.         lpstr=get_memory(lstrlen(lpelf->elfStyle)+1);
  371.         if(!successful_so_far)return 0;
  372.         lstrcpy(lpstr,lpelf->elfStyle);
  373.         break;
  374.     }
  375.     if(lpelf->elfLogFont.lfItalic){
  376.         if(lpelf->elfLogFont.lfWeight>FW_REGULAR){
  377.             fonts[fams]->flags|=FONTHASBOLDITALIC;
  378.             fonts[fams]->bolditalic=(lpstr==NULL)?"Bold Italic":lpstr;
  379.         }
  380.         else{
  381.             fonts[fams]->flags|=FONTHASITALIC;
  382.             fonts[fams]->italic=(lpstr==NULL)?"Italic":lpstr;
  383.         }
  384.     }
  385.     else{
  386.         if(lpelf->elfLogFont.lfWeight>FW_REGULAR){
  387.             fonts[fams]->flags|=FONTHASBOLD;
  388.             fonts[fams]->bold=(lpstr==NULL)?"Bold":lpstr;
  389.         }
  390.         else{
  391.             fonts[fams]->flags|=FONTHASREGULAR;
  392.             fonts[fams]->regular=(lpstr==NULL)?"Regular":lpstr;
  393.         }
  394.     }
  395.     return 1;
  396. }
  397.  
  398. // uses Borland's EasyWin library to write trace file
  399. #ifdef DEBUG
  400. static int mprintf(const char *fmt,...){
  401.     char buf[300];
  402.     int retval;
  403.     va_list ap;
  404.     va_start(ap,fmt);
  405.     retval=wvsprintf(buf,fmt,ap);
  406.     va_end(ap);
  407.     #undef printf
  408.     if(retval){
  409.         if(file!=HFILE_ERROR)_lwrite(file,buf,retval);
  410.         else printf(buf);
  411.     }
  412.     #define printf mprintf
  413.     return retval;
  414. }
  415. #endif
  416.  
  417. // uses Common Dialog Box to get SaveAs filename
  418. // for output .WRI file. defaults to putting file
  419. // into same directory in which FntPrn resides.
  420. static void open_output_file(void){
  421.     static char filenamebuffer[256];
  422.     char startdir[256];
  423.     BOOL ofn_success;
  424.     /* initialize ofn structure */
  425.     ofn.lStructSize=sizeof(OPENFILENAME);
  426.     ofn.hwndOwner=hwndDialog;
  427.     ofn.hInstance=instance;
  428.     ofn.lpstrFilter=(LPCSTR)"Write Files (*.wri)\0*.wri\0";
  429.     ofn.lpstrCustomFilter=NULL;
  430.     ofn.nFilterIndex=0;
  431.     lstrcpy(filenamebuffer,"fntprn.wri");
  432.     ofn.lpstrFile=(LPSTR)filenamebuffer;
  433.     ofn.nMaxFile=256;
  434.     ofn.lpstrFileTitle=NULL;
  435.     if(GetModuleFileName(instance,(LPSTR)startdir,256)){
  436.         // first, strip off filename @ end
  437.         char *p=startdir,*b=&startdir[3];
  438.         while(*p)p++;
  439.         while(p>b){
  440.             p--;
  441.             if(*p=='\\'){*p=0;break;}
  442.             *p--=0;
  443.         }
  444.         ofn.lpstrInitialDir=(LPSTR)startdir;
  445.     }
  446.     else ofn.lpstrInitialDir=NULL;
  447.     ofn.lpstrTitle=(LPSTR)"Choose Output Filename";
  448.     ofn.Flags=OFN_HIDEREADONLY|OFN_NOREADONLYRETURN|
  449.         OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST;
  450.     ofn.lpstrDefExt=(LPSTR)"WRI";
  451.     // Allow user to make file selection
  452.     ofn_success=GetOpenFileName(&ofn);
  453.     if(!ofn_success){
  454.         file=HFILE_ERROR;
  455.         successful_so_far=0;
  456.         bailout(NULL);
  457.         return;
  458.     }
  459.     // Try to open the file
  460.     file=_lcreat(ofn.lpstrFile,0);
  461.     if(file==HFILE_ERROR)bailout("Could not create file");
  462. }
  463.  
  464. // fills the fonts[] array
  465. static void gather_data(void){
  466.     if(NULL==(do_families=MakeProcInstance(families,instance))){
  467.         bailout("Internal Error (families)");
  468.         return;
  469.     }
  470.     if(NULL==(do_individuals=MakeProcInstance(individuals,instance))){
  471.         bailout("Internal Error (individuals)");
  472.         return;
  473.     }
  474.     create_device_context();
  475.     if(!successful_so_far)return;
  476.     EnumFontFamilies(hdc,NULL,do_families,NULL);
  477.     if(fams<1){
  478.         bailout("No fonts found");
  479.         return;
  480.     }
  481.     if(fams>60){
  482.         MessageBox(hwndDialog,"You selected more than 60 fonts.\n\n"
  483.         "Write may not display or print them correctly.\n\n"
  484.         "Importing this file into a word processor may work better.",
  485.         "Caution",MB_OK|MB_ICONINFORMATION);
  486.     }
  487. }
  488.  
  489. // sorter() does the actual work
  490. static void sort_data(void){
  491.     if(fams>1)qsort(fonts,fams,sizeof(fonts[0]),sorter);
  492. }
  493.  
  494. // callback function for qsort() 
  495. static int sorter(const void* arg1,const void* arg2){
  496.     LPTRACKFONT p1=*(LPTRACKFONT*)arg1,p2=*(LPTRACKFONT*)arg2;
  497.     int ft1,ft2;
  498.     switch(sortorder){
  499.     case HEIGHT:
  500.         if(p1->height>p2->height)return 1;
  501.         if(p1->height<p2->height)return -1;
  502.         break;
  503.     case WIDTH:
  504.         if(p1->width>p2->width)return 1;
  505.         if(p1->width<p2->width)return -1;
  506.         break;
  507.     case NARROWNESS:
  508.         if(p1->narrowness>p2->narrowness)return 1;
  509.         if(p1->narrowness<p2->narrowness)return -1;
  510.         break;
  511.     case WEIGHT:
  512.         if(p1->weight>p2->weight)return 1;
  513.         if(p1->weight<p2->weight)return -1;
  514.         break;
  515.     case FONTTYPE:
  516.         ft1=(int)p1->fonttype;
  517.         ft2=(int)p2->fonttype;
  518.         if(ft1&~3>ft2&~3)return 1;
  519.         if(ft1&~3<ft2&~3)return -1;
  520.         break;
  521.     }
  522.     // if primary sort is ALPHABETIC or the primary
  523.     // sort was a tie (both the same width, for example)
  524.     // then sort by font name
  525.     return lstrcmpi(p1->facename,p2->facename);
  526. }
  527.  
  528. // just initializes get_memory() block to zeros
  529. static void FAR* get_zeroed_memory(size_t size){
  530.     void FAR* retval;
  531.     char FAR* cp;
  532.     retval=get_memory(size);
  533.     if(retval!=NULL){
  534.         cp=retval;
  535.         while(size--)*cp++=0;
  536.     }
  537.     return retval;
  538. }
  539.  
  540. // elementary suballocator to avoid making tons
  541. // of direct calls to GlobalAlloc()
  542. // memory actually allocated ALLOCATIONSIZE bytes
  543. // at a time, handles stored in mem_handles[]
  544. static void FAR* get_memory(size_t size){
  545.     static size_t memory_left;
  546.     static char FAR* available_memory;
  547.     void FAR* retval;
  548.     if(memory_system_restart){
  549.         memory_left=0;
  550.         memory_system_restart=0;
  551.     }
  552.     if(size<1)size=1;
  553.     while(size>memory_left){
  554.         if(mem_handles_used==MAXALLOCATIONS)break;
  555.         mem_handles[mem_handles_used]=
  556.             GlobalAlloc(GMEM_MOVEABLE,ALLOCATIONSIZE);
  557.         if(mem_handles[mem_handles_used]==NULL)break;
  558.         available_memory=GlobalLock(mem_handles[mem_handles_used]);
  559.         if(available_memory==NULL){
  560.             GlobalFree(mem_handles[mem_handles_used]);
  561.             break;
  562.         }
  563.         memory_left=ALLOCATIONSIZE;
  564.         mem_handles_used++;
  565.         break;
  566.     }
  567.     if(size>memory_left)bailout("Out of memory");
  568.     retval=available_memory;
  569.     memory_left-=size;
  570.     available_memory+=size;
  571.     return retval;
  572. }
  573.  
  574. // frees the handles in mem_handles[] previously
  575. // allocated by way of get_memory()
  576. static void free_memory(void){
  577.     while(mem_handles_used--){
  578.         GlobalUnlock(mem_handles[mem_handles_used]);
  579.         GlobalFree(mem_handles[mem_handles_used]);
  580.     }
  581.     mem_handles_used=0;
  582.     memory_system_restart=1;
  583. }
  584.  
  585. // creates .WRI file by first creating the data
  586. // in memory using TEXTQUEUE singly linked lists,
  587. // then writes the file out
  588. static void generate_report(void){
  589.     int x;
  590.     w_init();
  591.     if(!successful_so_far)return;
  592.     // write selection data
  593.     {
  594.         char* sortordername;
  595.         char* monospacename;
  596.         switch(sortorder){
  597.         case HEIGHT:
  598.             sortordername="character height";
  599.             break;
  600.         case WIDTH:
  601.             sortordername="character width";
  602.             break;
  603.         case NARROWNESS:
  604.             sortordername="character height divided by character width";
  605.             break;
  606.         case WEIGHT:
  607.             sortordername="character weight";
  608.             break;
  609.         case FONTTYPE:
  610.             sortordername="font family";
  611.             break;
  612.         default:
  613.             sortordername="font name";
  614.             break;
  615.         }
  616.         switch(monospace){
  617.         case VAR:
  618.             monospacename="Variable pitch only. ";
  619.             break;
  620.         case MONO:
  621.             monospacename="Monospace only. ";
  622.             break;
  623.         default:
  624.             monospacename="";
  625.             break;
  626.         }
  627.         w_default(
  628.             "%d font famil%s found%s%s%s%s%s%s."
  629.             "%s For %s. "
  630.             "Synthetic bold and italic %sallowed%s%s%s%s. "
  631.             "%sSorted by %s."
  632.             "\r\n",
  633.             fams,
  634.             (LPSTR)(fams>1?"ies":"y"),
  635.             (LPSTR)(incl_roman?", Roman":""),
  636.             (LPSTR)(incl_modern?", modern":""),
  637.             (LPSTR)(incl_sanserif?", sans serif":""),
  638.             (LPSTR)(incl_script?", script":""),
  639.             (LPSTR)(incl_novelty?", novelty":""),
  640.             (LPSTR)(incl_other?", other/unknown":""),
  641.  
  642.             (LPSTR)(truetype_only?" TrueType only.":""),
  643.             (LPSTR)(use_printer_context?"printer":"screen"),
  644.  
  645.             (LPSTR)(((incl_bold||incl_italic||incl_bolditalic)&&allow_synthesis)?"":"not "),
  646.             (LPSTR)(incl_regular?", regular":""),
  647.             (LPSTR)(incl_bold?", bold":""),
  648.             (LPSTR)(incl_italic?", italic":""),
  649.             (LPSTR)(incl_bolditalic?", bold-italic":""),
  650.  
  651.  
  652.             (LPSTR)monospacename,
  653.             (LPSTR)sortordername
  654.         );
  655.     }
  656.     // write data for each family
  657.     for(x=0;x<fams;x++){
  658.         if(!successful_so_far)return;
  659.         if(fonts[x]->flags&FONTHASREGULAR)
  660.             w_sample(fonts[x],0);
  661.         if(!successful_so_far)return;
  662.         if(fonts[x]->flags&FONTHASBOLD)
  663.             w_sample(fonts[x],BOLD_BIT);
  664.         if(!successful_so_far)return;
  665.         if(fonts[x]->flags&FONTHASITALIC)
  666.             w_sample(fonts[x],ITALIC_BIT);
  667.         if(!successful_so_far)return;
  668.         if(fonts[x]->flags&FONTHASBOLDITALIC)
  669.             w_sample(fonts[x],BOLD_BIT|ITALIC_BIT);
  670.         if(!successful_so_far)return;
  671.         w_default("*** %s%s%s%s%s%s%s%s%s. %s pitch, %s font "
  672.             "family,%s TrueType\r\n",
  673.             fonts[x]->facename,
  674.             (LPSTR)(fonts[x]->flags&FONTHASREGULAR?", ":""),
  675.             fonts[x]->flags&FONTHASREGULAR?fonts[x]->regular:(LPSTR)"",
  676.             (LPSTR)(fonts[x]->flags&FONTHASBOLD?", ":""),
  677.             fonts[x]->flags&FONTHASBOLD?fonts[x]->bold:(LPSTR)"",
  678.             (LPSTR)(fonts[x]->flags&FONTHASITALIC?", ":""),
  679.             fonts[x]->flags&FONTHASITALIC?fonts[x]->italic:(LPSTR)"",
  680.             (LPSTR)(fonts[x]->flags&FONTHASBOLDITALIC?", ":""),
  681.             fonts[x]->flags&FONTHASBOLDITALIC?fonts[x]->bolditalic:(LPSTR)"",
  682.             (LPSTR)(fonts[x]->flags&FONTISFIXEDWIDTH?"Fixed":"Variable"),
  683.             get_font_type(fonts[x]->fonttype),
  684.             (LPSTR)(fonts[x]->flags&FONTISTRUETYPE?"":" not"));
  685.     }
  686. }
  687.  
  688. // sets global variables for .WRI file generation
  689. static void w_init(void){
  690.     text_bytes=0;
  691.     char_pages=0;
  692.     graf_pages=0;
  693.     font_pages=0;
  694.     text_first=text_last=char_first=char_last=
  695.         graf_first=graf_last=font_first=font_last=NULL;
  696.     default_font_offset=w_add_font(default_font,default_ffid);
  697. }
  698.  
  699. // adds a line of data in default_pointsize,
  700. // default_bolditalic, default_font_offset,
  701. // default_just to .WRI file in memory
  702. static void w_default(const char* fmt,...){
  703.     LPSTR newtextspace;
  704.     static char buf[512];           // for font names, etc.
  705.     int retval;
  706.     va_list ap;
  707.     va_start(ap,fmt);
  708.     retval=wvsprintf(buf,fmt,ap);
  709.     va_end(ap);
  710.     if(!retval)return;
  711.     newtextspace=get_memory(retval);
  712.     if(!successful_so_far)return;
  713.     lstrcpy(newtextspace,buf);
  714.     w_add_char(retval,default_bolditalic,default_font_offset,
  715.         default_pointsize);
  716.     w_add_graf(retval,default_just);
  717.     w_add_text(newtextspace,retval);
  718. }
  719.  
  720. // adds a line of data in the specified font to
  721. // the .WRI file in memory. used to add the actual
  722. // sample text (AENOPS, the alphabet, whatever) to
  723. // the report
  724. static void w_sample(LPTRACKFONT lpf,int bolditalic){
  725.     int fontcode=w_add_font(lpf->facename,lpf->fonttype);
  726.     w_add_char(sample_text_length,bolditalic,fontcode,sample_text_pointsize);
  727.     w_add_graf(sample_text_length,sample_text_just);
  728.     w_add_text(sample_text_ptr,sample_text_length);
  729. }
  730.  
  731. // adds a new font to the .WRI file in memory
  732. // this is the set of font names at the end of
  733. // the file
  734. static int w_add_font(LPSTR name, BYTE ffid){
  735.     static int cur_bytes_left;
  736.     static LPSTR previous_name=NULL;
  737.     static char FAR* next_byte;
  738.     static int FAR* numptr;
  739.     int bytes_to_use=3+lstrlen(name)+1;
  740.     int bytes_needed=bytes_to_use+2;
  741.     int FAR* fpi;
  742.     // don't duplicate last request...
  743.     if(name==previous_name)return *numptr-1;
  744.     else previous_name=name;
  745.     if(font_first==NULL){
  746.         font_first=get_memory(sizeof(TEXTQUEUE));
  747.         if(!successful_so_far)return 0;
  748.         font_first->text=get_zeroed_memory(0x80);
  749.         if(!successful_so_far)return 0;
  750.         font_first->textlen=0x80;
  751.         font_first->next=NULL;
  752.         cur_bytes_left=0x7E;
  753.         font_last=font_first;
  754.         numptr=(int FAR*)font_first->text;
  755.         next_byte=&font_first->text[2];
  756.         *numptr=0;
  757.         font_pages++;
  758.     }
  759.     if(bytes_needed>cur_bytes_left){
  760.         if(bytes_needed>0x70){
  761.             bailout("Windows reports too-long font name");
  762.         }
  763.         fpi=(int FAR*)next_byte;
  764.         *fpi=-1;                        // mark last block
  765.         font_last->next=get_memory(sizeof(TEXTQUEUE));    
  766.         if(!successful_so_far)return 0;
  767.         font_last=font_last->next;
  768.         font_last->text=get_zeroed_memory(0x80);
  769.         if(!successful_so_far)return 0;
  770.         font_last->textlen=0x80;
  771.         font_last->next=NULL;
  772.         cur_bytes_left=0x80;
  773.         next_byte=font_last->text;
  774.         font_pages++;
  775.     }
  776.     fpi=(int FAR*)next_byte;
  777.     *fpi=bytes_to_use-2;
  778.     next_byte[2]=ffid&~3;
  779.     lstrcpy(&next_byte[3],name);
  780.     next_byte+=bytes_to_use;
  781.     cur_bytes_left-=bytes_to_use;
  782.     *numptr+=1;
  783.     return *numptr-1;
  784. }
  785.  
  786. // used to add new text data to the .WRI file
  787. // in memory
  788. static void w_add_graf(int textlen,int just){
  789.     static int cur_bytes_left;
  790.     static char FAR* next_byte;
  791.     static char FAR* fod_count;
  792.     int total_bytes_needed;
  793.     FOD fod;
  794.     PAP pap;
  795.     LPPAP lppap;
  796.     if(graf_first==NULL){
  797.         graf_first=get_memory(sizeof(TEXTQUEUE));
  798.         if(!successful_so_far)return;
  799.         graf_last=graf_first;
  800.         graf_last->text=get_zeroed_memory(0x80);
  801.         if(!successful_so_far)return;
  802.         graf_last->textlen=0x80;
  803.         graf_last->next=NULL;
  804.         cur_bytes_left=0x7B;
  805.         next_byte=&graf_last->text[4];
  806.         ((long FAR*)next_byte)[-1]=text_bytes+0x80;
  807.         fod_count=&graf_last->text[127];
  808.         graf_pages++;
  809.     }
  810.     pap.len=sizeof(PAP)-1;
  811.     pap.res1=0;
  812.     pap.just=(unsigned char)just;
  813.     total_bytes_needed=sizeof(FOD)+sizeof(PAP);
  814.     if(total_bytes_needed>cur_bytes_left){
  815.         graf_last->next=get_memory(sizeof(TEXTQUEUE));
  816.         if(!successful_so_far)return;
  817.         graf_last=graf_last->next;
  818.         graf_last->text=get_zeroed_memory(0x80);
  819.         if(!successful_so_far)return;
  820.         graf_last->textlen=0x80;
  821.         graf_last->next=NULL;
  822.         cur_bytes_left=0x7B;
  823.         next_byte=&graf_last->text[4];
  824.         ((long FAR*)next_byte)[-1]=text_bytes+0x80;
  825.         fod_count=&graf_last->text[127];
  826.         graf_pages++;
  827.     }
  828.     cur_bytes_left-=sizeof(PAP);
  829.     lppap=(LPPAP)(next_byte+cur_bytes_left);
  830.     *lppap=pap;
  831.     fod.bfprop=(char FAR*)lppap-(char FAR*)graf_last->text-4;
  832.     fod.fcLim=text_bytes+textlen+0x80;
  833.     *(LPFOD)next_byte=fod;
  834.     next_byte+=sizeof(FOD);
  835.     cur_bytes_left-=sizeof(FOD);
  836.     *fod_count+=1;
  837. }
  838.  
  839. // used to add character data to the .WRI file in memory
  840. static void w_add_char(int textlen,int bolditalic,int fontcode,int size){
  841.     static int cur_bytes_left;
  842.     static char FAR* next_byte;
  843.     static char FAR* fod_count;
  844.     int total_bytes_needed;
  845.     FOD fod;
  846.     CHP5 chp5;
  847.     LPCHP5 lpchp5;
  848.     LPCHP3 lpchp3;
  849.     if(char_first==NULL){
  850.         char_first=get_memory(sizeof(TEXTQUEUE));
  851.         if(!successful_so_far)return;
  852.         char_last=char_first;
  853.         char_last->text=get_zeroed_memory(0x80);
  854.         if(!successful_so_far)return;
  855.         char_last->textlen=0x80;
  856.         char_last->next=NULL;
  857.         cur_bytes_left=0x7B;
  858.         next_byte=&char_last->text[4];
  859.         ((long FAR*)next_byte)[-1]=text_bytes+0x80;
  860.         fod_count=&char_last->text[127];
  861.         char_pages++;
  862.     }
  863.     chp5.res1=0;
  864.     chp5.bold_it_fontLSBs=(unsigned char)((fontcode<<2)|bolditalic);
  865.     chp5.fontsiz=(unsigned char)size;
  866.     chp5.uline=0;
  867.     chp5.fontMSBs=(unsigned char)(fontcode>>6);
  868.     chp5.len=chp5.fontMSBs?sizeof(CHP5)-1:sizeof(CHP3)-1;
  869.     total_bytes_needed=sizeof(FOD)+(chp5.fontMSBs?sizeof(CHP5):sizeof(CHP3));
  870.     if(total_bytes_needed>cur_bytes_left){
  871.         char_last->next=get_memory(sizeof(TEXTQUEUE));
  872.         if(!successful_so_far)return;
  873.         char_last=char_last->next;
  874.         char_last->text=get_zeroed_memory(0x80);
  875.         if(!successful_so_far)return;
  876.         char_last->textlen=0x80;
  877.         char_last->next=NULL;
  878.         cur_bytes_left=0x7B;
  879.         next_byte=&char_last->text[4];
  880.         ((long FAR*)next_byte)[-1]=text_bytes+0x80;
  881.         fod_count=&char_last->text[127];
  882.         char_pages++;
  883.     }
  884.     if(chp5.fontMSBs){
  885.         cur_bytes_left-=sizeof(CHP5);
  886.         lpchp5=(LPCHP5)(next_byte+cur_bytes_left);
  887.         *lpchp5=chp5;
  888.         fod.bfprop=(char FAR*)lpchp5-(char FAR*)char_last->text-4;
  889.     }
  890.     else{
  891.         cur_bytes_left-=sizeof(CHP3);
  892.         lpchp3=(LPCHP3)(next_byte+cur_bytes_left);
  893.         *lpchp3=*(LPCHP3)&chp5;
  894.         fod.bfprop=(char FAR*)lpchp3-(char FAR*)char_last->text-4;
  895.     }
  896.     fod.fcLim=text_bytes+textlen+0x80;
  897.     *(LPFOD)next_byte=fod;
  898.     next_byte+=sizeof(FOD);
  899.     cur_bytes_left-=sizeof(FOD);
  900.     *fod_count+=1;
  901. }
  902.  
  903. // adds report data to .WRI file in memory, appending
  904. // to text_first queue
  905. static void w_add_text(LPSTR text,int size){
  906.     if(text_first==NULL){
  907.         text_first=get_memory(sizeof(TEXTQUEUE));
  908.         if(!successful_so_far)return;
  909.         text_last=text_first;
  910.     }
  911.     else{
  912.         text_last->next=get_memory(sizeof(TEXTQUEUE));
  913.         if(!successful_so_far)return;
  914.         text_last=text_last->next;
  915.     }
  916.     text_last->text=text;
  917.     text_last->textlen=size;
  918.     text_last->next=NULL;
  919.     text_bytes+=size;
  920. }
  921.  
  922. // now all data is prepared in memory, so write it all
  923. // out. header first, then report contents, then character
  924. // data, then paragraph data, then font names
  925. static void write_data_file(void){
  926.     long text_pages;
  927.     LPWRITEFILEHEADER wfh=get_zeroed_memory(sizeof(WRITEFILEHEADER));
  928.     if(!successful_so_far)return;
  929.     wfh->wIdent=0xBE31;
  930.     wfh->wTool=0xAB00;
  931.     wfh->fcMac=text_bytes+0x80;
  932.     {                                   // pad the text to 128-byte boundary
  933.         int bytes_needed=0x80-text_bytes%0x80;
  934.         LPSTR newspace;
  935.         if(bytes_needed){
  936.             newspace=get_zeroed_memory(bytes_needed);
  937.             if(!successful_so_far)return;
  938.             w_add_text(newspace,bytes_needed);
  939.             if(!successful_so_far)return;
  940.         }
  941.         text_pages=text_bytes/0x80;
  942.     }
  943.     wfh->pnPara=1+text_pages+char_pages;
  944.     wfh->pnFntb=wfh->pnSep=wfh->pnSetb=wfh->pnPgtb=wfh->pnFfntb=
  945.         1+text_pages+char_pages+graf_pages;
  946.     wfh->pnMac=1+text_pages+char_pages+graf_pages+font_pages;
  947.                                         // write header
  948.     if(!write_data_chunk((LPSTR)wfh,sizeof(WRITEFILEHEADER)))return;
  949.     {                                   // write text
  950.         LPTEXTQUEUE l=text_first;
  951.         while(l){
  952.             if(!(write_data_chunk(l->text,l->textlen)))return;
  953.             l=l->next;
  954.         }
  955.     }
  956.     {                                   // write char data
  957.         LPTEXTQUEUE l=char_first;
  958.         while(l){
  959.             if(!(write_data_chunk(l->text,l->textlen)))return;
  960.             l=l->next;
  961.         }
  962.     }
  963.     {                                   // write graf data
  964.         LPTEXTQUEUE l=graf_first;
  965.         while(l){
  966.             if(!(write_data_chunk(l->text,l->textlen)))return;
  967.             l=l->next;
  968.         }
  969.     }
  970.     {                                   // write font data
  971.         LPTEXTQUEUE l=font_first;
  972.         while(l){
  973.             if(!(write_data_chunk(l->text,l->textlen)))return;
  974.             l=l->next;
  975.         }
  976.     }
  977. }
  978.  
  979. // helper function for write_data_file()
  980. static int write_data_chunk(LPSTR buf,size_t buflen){
  981.     if(file==HFILE_ERROR||!successful_so_far)return 0;
  982.     if((UINT)buflen!=_lwrite(file,buf,buflen)){
  983.         bailout("Error writing file");
  984.         return 0;
  985.     }
  986.     return 1;    
  987. }
  988.  
  989. // need device context for EnumFontFamilies()
  990. static void create_device_context(void){
  991.     if(use_printer_context){ // based on Petzold 3rd ed., p. 707
  992.         char pr[100];
  993.         char *dev,*driver,*output;
  994.         GetProfileString("windows","device","",pr,sizeof(pr));
  995.         if((dev=strtok(pr,","))==NULL||
  996.         (driver=strtok(NULL,", "))==NULL||
  997.         (output=strtok(NULL,", "))==NULL)
  998.             bailout("Printer driver information unavailable");
  999.         else{
  1000.             hdc=CreateIC(driver,dev,output,NULL);
  1001.             if(hdc==NULL)bailout("Internal Error (printer context)");
  1002.         }
  1003.     }
  1004.     else{
  1005.         hdc=CreateIC("DISPLAY",NULL,NULL,NULL);
  1006.         if(hdc==NULL)bailout("Internal Error (display context)");
  1007.     }
  1008. }
  1009.  
  1010. // all the rest is test scaffolding to create text-mode Win
  1011. // app to test file generation code
  1012. #ifdef DEBUG
  1013. #include<conio.h>
  1014. static void get_user_options(void){
  1015.     int failure;
  1016.     wanna_quit=1;
  1017.     for(;;){
  1018.         failure=0;
  1019.         printf("want to quit now? (y/n): ");
  1020.         switch(getch()){
  1021.         case 'y': case 'Y': wanna_quit=1;   return;
  1022.         case 'n': case 'N': wanna_quit=0;   break;
  1023.         default: failure=1;
  1024.         }
  1025.         printf("\n");
  1026.         if(!failure)break;
  1027.     }
  1028.     for(;;){
  1029.         failure=0;
  1030.         printf("sort order (a)lpha, (h)eight, (w)idth, "
  1031.             "(n)arrowness, w(e)ight, (f)onttype: ");
  1032.         switch(getch()){
  1033.         case 'a': case 'A': sortorder=ALPHA;        break;
  1034.         case 'h': case 'H': sortorder=HEIGHT;       break;
  1035.         case 'w': case 'W': sortorder=WIDTH;        break;
  1036.         case 'n': case 'N': sortorder=NARROWNESS;   break;
  1037.         case 'e': case 'E': sortorder=WEIGHT;       break;
  1038.         case 'f': case 'F': sortorder=FONTTYPE;     break;
  1039.         default: failure=1;
  1040.         }
  1041.         printf("\n");
  1042.         if(!failure)break;
  1043.     }
  1044.     for(;;){
  1045.         failure=0;
  1046.         printf("monospace (m)ono (v)ariable (b)oth: ");
  1047.         switch(getch()){
  1048.         case 'm': case 'M': monospace=MONO;     break;
  1049.         case 'v': case 'V': monospace=VAR;      break;
  1050.         case 'b': case 'B': monospace=VARMONO;  break;
  1051.         default: failure=1;
  1052.         }
  1053.         printf("\n");
  1054.         if(!failure)break;
  1055.     }
  1056.     for(;;){
  1057.         failure=0;
  1058.         printf("use_printer_context? (y/n): ");
  1059.         switch(getch()){
  1060.         case 'y': case 'Y': use_printer_context=1;break;
  1061.         case 'n': case 'N': use_printer_context=0;break;
  1062.         default: failure=1;
  1063.         }
  1064.         printf("\n");
  1065.         if(!failure)break;
  1066.     }
  1067.     for(;;){
  1068.         failure=0;
  1069.         printf("allow_synthesis? (y/n): ");
  1070.         switch(getch()){
  1071.         case 'y': case 'Y': allow_synthesis=1;break;
  1072.         case 'n': case 'N': allow_synthesis=0;break;
  1073.         default: failure=1;
  1074.         }
  1075.         printf("\n");
  1076.         if(!failure)break;
  1077.     }
  1078.     for(;;){
  1079.         failure=0;
  1080.         printf("truetype_only? (y/n): ");
  1081.         switch(getch()){
  1082.         case 'y': case 'Y': truetype_only=1;break;
  1083.         case 'n': case 'N': truetype_only=0;break;
  1084.         default: failure=1;
  1085.         }
  1086.         printf("\n");
  1087.         if(!failure)break;
  1088.     }
  1089.     for(;;){
  1090.         failure=0;
  1091.         printf("incl_novelty? (y/n): ");
  1092.         switch(getch()){
  1093.         case 'y': case 'Y': incl_novelty=1;break;
  1094.         case 'n': case 'N': incl_novelty=0;break;
  1095.         default: failure=1;
  1096.         }
  1097.         printf("\n");
  1098.         if(!failure)break;
  1099.     }
  1100.     for(;;){
  1101.         failure=0;
  1102.         printf("incl_modern? (y/n): ");
  1103.         switch(getch()){
  1104.         case 'y': case 'Y': incl_modern=1;break;
  1105.         case 'n': case 'N': incl_modern=0;break;
  1106.         default: failure=1;
  1107.         }
  1108.         printf("\n");
  1109.         if(!failure)break;
  1110.     }
  1111.     for(;;){
  1112.         failure=0;
  1113.         printf("incl_roman? (y/n): ");
  1114.         switch(getch()){
  1115.         case 'y': case 'Y': incl_roman=1;break;
  1116.         case 'n': case 'N': incl_roman=0;break;
  1117.         default: failure=1;
  1118.         }
  1119.         printf("\n");
  1120.         if(!failure)break;
  1121.     }
  1122.     for(;;){
  1123.         failure=0;
  1124.         printf("incl_script? (y/n): ");
  1125.         switch(getch()){
  1126.         case 'y': case 'Y': incl_script=1;break;
  1127.         case 'n': case 'N': incl_script=0;break;
  1128.         default: failure=1;
  1129.         }
  1130.         printf("\n");
  1131.         if(!failure)break;
  1132.     }
  1133.     for(;;){
  1134.         failure=0;
  1135.         printf("incl_sanserif? (y/n): ");
  1136.         switch(getch()){
  1137.         case 'y': case 'Y': incl_sanserif=1;break;
  1138.         case 'n': case 'N': incl_sanserif=0;break;
  1139.         default: failure=1;
  1140.         }
  1141.         printf("\n");
  1142.         if(!failure)break;
  1143.     }
  1144.     for(;;){
  1145.         failure=0;
  1146.         printf("incl_other? (y/n): ");
  1147.         switch(getch()){
  1148.         case 'y': case 'Y': incl_other=1;break;
  1149.         case 'n': case 'N': incl_other=0;break;
  1150.         default: failure=1;
  1151.         }
  1152.         printf("\n");
  1153.         if(!failure)break;
  1154.     }
  1155.     for(;;){
  1156.         failure=0;
  1157.         printf("incl_regular? (y/n): ");
  1158.         switch(getch()){
  1159.         case 'y': case 'Y': incl_regular=1;break;
  1160.         case 'n': case 'N': incl_regular=0;break;
  1161.         default: failure=1;
  1162.         }
  1163.         printf("\n");
  1164.         if(!failure)break;
  1165.     }
  1166.     for(;;){
  1167.         failure=0;
  1168.         printf("incl_bold? (y/n): ");
  1169.         switch(getch()){
  1170.         case 'y': case 'Y': incl_bold=1;break;
  1171.         case 'n': case 'N': incl_bold=0;break;
  1172.         default: failure=1;
  1173.         }
  1174.         printf("\n");
  1175.         if(!failure)break;
  1176.     }
  1177.     for(;;){
  1178.         failure=0;
  1179.         printf("incl_italic? (y/n): ");
  1180.         switch(getch()){
  1181.         case 'y': case 'Y': incl_italic=1;break;
  1182.         case 'n': case 'N': incl_italic=0;break;
  1183.         default: failure=1;
  1184.         }
  1185.         printf("\n");
  1186.         if(!failure)break;
  1187.     }
  1188.     for(;;){
  1189.         failure=0;
  1190.         printf("incl_bolditalic? (y/n): ");
  1191.         switch(getch()){
  1192.         case 'y': case 'Y': incl_bolditalic=1;break;
  1193.         case 'n': case 'N': incl_bolditalic=0;break;
  1194.         default: failure=1;
  1195.         }
  1196.         printf("\n");
  1197.         if(!failure)break;
  1198.     }
  1199.     sample_text_ptr="PANOSE abegmoqstfy\r\n";
  1200.     sample_text_length=lstrlen(sample_text_ptr);
  1201.     sample_text_pointsize=20;
  1202.     sample_text_just=JUST_JUST;
  1203.     default_font="Arial";
  1204.     default_ffid=FF_SWISS;
  1205.     default_pointsize=14;
  1206.     default_just=JUST_LEFT;
  1207.     default_bolditalic=0;
  1208. }
  1209. #endif
  1210.