#define VERSION "0.44" #define MYVERSION "/T.63dt\0" /**************************************************************************** Line breaking program for MusiXTeX. Ross Mitchell, August 1992. - enabled endline signature changes, May 1993 - enabled \zbar, March 1994 - enabled \leftrightrepeat at eoline, April 1994 - converted to (TURBO/PURBO/Pure)C, thanks to MiSi for compiling, June 1994 remark: this is my very first attempt using C, if your harddisk crushes or your computer blows up -> Your problem ! - MusixFlx now gives back a number to the parent process (batch, shell, o.s.e.) 0 -> OK 3 -> error (freely be changed in error_exit()) - introduced \raggedstoppiece, August 1994 - introduced barno for more transparence of .mx2, September 1994 - introduced (reluctant) the use of 'hard' offsets, September 1994 therefore the computing of mean space factor changed - introduced \leftrepeat, September 1994 - enabled moretimes use of \startpiece, September 1994 - added logfile for bughunting, September 1994 - added test of versionnumber from MusiXTeX, September 1994 - reintroduced \autolines, October 1994 - renamed MuFlex to musixflx (as suggested by DT), October 1994 - adapted ANSI coding (as suggested by CLARY Olivier), February 1995 - added some safeties for weird situations, March 1995 *****************************************************************************/ #include #include #include #include #define TRUE 1 #define FALSE 0 /* attention: every \changecontext reports a change of \sign@skip */ #define MAX_SIGNS 128 /* max signature changes */ #define MAX_SECTIONS 128 /* max sections */ #define MAX_BARS 2048 /* max number of bars */ #define GETLINE fgets(linebuf, (int) sizeof(linebuf), infile) /* ! If next line causes trouble, comment it out ! */ void error_exit(int error_number); int zbar[MAX_BARS], lr_repeat[MAX_BARS], raggedline[MAX_BARS], l_repeat[MAX_BARS], barno[MAX_BARS], autolines[MAX_SECTIONS], bars[MAX_SECTIONS], mulooseness[MAX_SECTIONS], signchange[MAX_SIGNS]; double hardbarlength[MAX_BARS], softbarlength[MAX_BARS], width_leftrightrepeat[MAX_BARS], width_leftrepeat[MAX_BARS], eff_hardlength[MAX_SECTIONS], eff_softlength[MAX_SECTIONS], oldsignskip[MAX_SIGNS], signskip[MAX_SIGNS]; FILE *infile, *outfile, *logfile; char linebuf[128]; void error_exit(error_number) int error_number; { switch (error_number){ case 0: printf("\nFile error: Disk full ?\n"); exit(3); case 1: printf("\nUsage: musixflx filename [d|f|s] (optional for debug modes)\n"); exit(3); case 2: printf("\nThis shouldn't happen ! Too less bars or \\mulooseness too large ?\n"); exit(3); case 3: printf("\nThis shouldn't happen ! Too less bars in section !\n"); exit(3); case 4: printf("\nMissing endmark ! Forgotten \\stop[end]piece ?\n"); exit(3); case 5: printf("\nDivision by zero ! Ask a wizard !\n"); exit(3); default: printf("!!! Can't go on !!!\n"); exit(3);}} int main(argc, argv) int argc; char **argv; { register int i, j, bar; int junk= -9999, dbug= FALSE, dbug_lines= FALSE, dbug_logfile= FALSE, showresult= FALSE, detectraggedline= FALSE, currentline= 1, samechapter= TRUE, line_number= 0, chapterno= 1, detect_end, typ, jbar, sign, all_section, section, mark, lines, lastbarnumber, barsinline, lastbarno, firstbarno, line_in_section; double lthick=.4, flexit, linewidth, parindent, x, spc_factor, elemskip, cor_elemskip, beforerule, cor_beforerule, afterrule, cor_afterrule, lastbar, eff_linewidth, fill_length, hardlength, softlength, clefskip; char name_of_file [128], n_o_f [128], n_o_logfile[128], MusiXFlxVersion[6]; printf("\n <<< musixflex %s%s >>>\n", VERSION, MYVERSION); printf("\n ... decoding command line\n"); if (argc<2 || argc >3) error_exit(1); /********************************* debugging d debug informations on screen f debug informations to file .mxl s show computed lines on screen **********************************/ if (argc==3){ if (!strcmp("d",argv[2])) dbug=TRUE; if (!strcmp("m",argv[2])) dbug_lines=TRUE; if (!strcmp("f",argv[2])){dbug=TRUE; dbug_logfile=TRUE; dbug_lines=TRUE;} if (!strcmp("s",argv[2])) showresult=TRUE;} /************************************** search for '.', cut string, add '.mx1' ***************************************/ strcpy (name_of_file, argv[1]); strcpy(n_o_f, strtok(name_of_file, ".")); strcat(name_of_file, ".mx1"); /***************************************************** Open the .mx1 file containing bar length information. ******************************************************/ printf(" ... open <%s> for input\n", name_of_file); infile = fopen( name_of_file, "r"); if (!infile){ printf("\nFile not found: %s\n", name_of_file); exit(3);} /*********************** test versionnumber and stop if they differ ************************/ strcpy(MusiXFlxVersion, VERSION); strcat(MusiXFlxVersion, "\n"); printf(" ... testing versionnumber\n"); ++currentline; if (GETLINE && strcmp(linebuf, MusiXFlxVersion)){ printf("\n!!! Wrong version !!!\n\nMusiXTeX : %s",linebuf); printf("musixflx : %s\n",MusiXFlxVersion); error_exit(99);} /********************* Open the output file. **********************/ strcpy (n_o_logfile, n_o_f); strcat (n_o_f, ".mx2"); printf(" ... open <%s> for output\n",n_o_f); outfile = fopen( n_o_f, "w" ); if (!outfile) {printf("\nCan't create: %s\n",n_o_f); exit(3);} /****************** Open the log file. *******************/ if (dbug_logfile){ strcat (n_o_logfile, ".mxl"); printf(" ... open <%s> for debugging\n",n_o_logfile); logfile = fopen( n_o_logfile, "w" ); if (!logfile) {printf("\nCan't create: %s\n",n_o_logfile); exit(3);} fprintf(logfile,"Version %s", MusiXFlxVersion);} /******************* skip startindicator ********************/ if (GETLINE && strcmp(linebuf,"S\n")){ printf("\nCorrupted <%s>\n", name_of_file); error_exit(99);} /***************************** do...while loop for moretimes call of \startpiece >>>>>>>>>>>>>>>>>>>>>>>>>>> ******************************/ GETLINE; do { /**************** reset all arrays *****************/ if (dbug) printf("\n------- Chapter %d -------\n\n", chapterno); if (dbug_logfile) fprintf(logfile, "\n------- Chapter %d -------\n\n", chapterno); for (i=0; i(MAX_SECTIONS-1)){ printf("\nToo many sections, maximum number of sections: %d\n", MAX_SECTIONS); exit(3);} jbar=junk; break; /********************************************************* autolines. Action: Right justify the material ending at the previous bar. Set flag. Reset the bar test integer to JUNK in case the bar number was reset between sections. ***********************************************************/ case 'a': autolines[all_section]=TRUE; ++all_section; if (all_section>(MAX_SECTIONS-1)){ printf("\nToo many sections, maximum number of sections: %d\n", MAX_SECTIONS); exit(3);} jbar=junk; break; /****************************************************** found a raggedline, let's set a flag I think, I'll hardly get a Nobel-Award for coding this What a pity! :-( but perhaps a Pulitzer-Award for my comments. :-) *******************************************************/ case 'r': raggedline[i+1]=TRUE; break; /************************************* found \zbar, set flag and store barno **************************************/ case 'z': zbar[i]=TRUE; barno[i]= (int) atol(strrchr(linebuf, ' ')); break; /***************************************** found a leftrightrepeat set a flag and store the different widths ******************************************/ case 'l': lr_repeat[i]=TRUE; /* printf("l found, i=%d\n",i); */ width_leftrightrepeat[i]=atof(strchr(linebuf, ' ')); /* printf("width_leftright=%f\n",width_leftrightrepeat[i]); */ width_leftrepeat[i]=atof(strrchr(linebuf, ' ')); /* printf("width_left=%f\n",width_leftrepeat[i]); */ break; /************************** found a leftrepeat set a flag and store width ***************************/ case 'L': l_repeat[i]=TRUE; width_leftrepeat[i]=atof(strrchr(linebuf, ' ')); break; /*********** store barno ************/ case 'b': barno[i]= (int) atol(strrchr(linebuf, ' ')); break; /********************************** enabling the use of 'hard' offsets advance current hardwith reduce current softwidth ***********************************/ case 'h': x = atof(strrchr(linebuf, ' ')); softbarlength[i] -= x; hardbarlength[i] += x; eff_softlength[all_section] -= x; eff_hardlength[all_section] += x; break; /*************************************************************** This record began with 's' and specifies a key signature change store the signskip, s.b. ***************************************************************/ case 's': ++sign; signchange[sign]=i; signskip[sign]=atof(strchr(linebuf,' ')); oldsignskip[sign]=hardbarlength[i]; break; /* comment */ case '%': break; /******************************************************************** This is an `ordinary' line, listing a contribution to the barlength. *********************************************************************/ default: if (!isdigit(linebuf[0])){ printf("\nError in <%s> line %d \n", name_of_file, currentline); error_exit(99);} bar= (int) atol(linebuf); typ= (int) atol(strchr(linebuf, ' ')); x=atof(strrchr(linebuf, ' ')); if (typ) eff_softlength[all_section] += x; else eff_hardlength[all_section] += x; /************************************** Increment bar number if the bar number read from the file has changed. Accumulate current bar length. ***************************************/ if (bar>jbar){ ++i; ++bars[all_section]; if(i>MAX_BARS){ printf("\nToo many bars, maximum number of bars: %d\n", MAX_BARS); exit(3);}} if (typ) softbarlength[i] += x; else hardbarlength[i] += x; jbar=bar; } /* eo switch */ } /* eo while */ /************************************************************** Decrement the number of sections if the final section is void. This will be the usual case where the input file ends with an end of section record. If this record has been omitted, stop going on to avoid 'You can't use \raise....'. ***************************************************************/ printf(" ... compute\n"); if (!bars[all_section]) --all_section; else error_exit(4); /******************************** Summarize sectioning information. *********************************/ if (dbug){ printf("\nNumber of sections : %d\n\n",all_section+1); for (section=0; section<=all_section; ++section){ if (autolines[section]) printf("---- autoline section ----\n"); printf("Section : %d\n",section+1); printf("Number of bars in section : %d\n",bars[section]); printf("Length(hard) of section %d : %f\n", section+1, eff_hardlength[section]); printf("Length(soft) of section %d : %f\n", section+1, eff_softlength[section]); printf("Looseness of section : %d\n",mulooseness[section]); getchar();}} if (dbug_logfile){ fprintf(logfile, "\nNumber of sections : %d\n\n", all_section+1); for (section=0; section<=all_section; ++section){ if (autolines[section]) fprintf(logfile, "---- autoline section ----\n"); fprintf(logfile, "Section : %d\n", section+1); fprintf(logfile, "Number of bars in section : %d\n", bars[section]); fprintf(logfile, "Length(hard) of section %d : %f\n", section+1, eff_hardlength[section]); fprintf(logfile, "Length(soft) of section %d : %f\n", section+1, eff_softlength[section]); fprintf(logfile, "Looseness of section : %d\n", mulooseness[section]);}} /************************************************* Loop over the sections defined in the input file. Each section must be right justified. LAST is the absolute number of the last bar in the current section. **************************************************/ sign = 0; mark = 0; lastbarnumber = 0; for(section=0; section<=all_section; ++section){ line_in_section=1; lastbarnumber += bars[section]; /************************************* Find number of lines to work towards. **************************************/ lines=((eff_hardlength[section]+eff_softlength[section]+parindent)/ (linewidth-(clefskip+signskip[sign])))+.5; if (!lines) lines=1; /* safety */ lines += mulooseness[section]; if (lines<1){lines=1; printf("Don't stress \\mulooseness to much !!!\n");} /************************************** autolinesflag set in current section ? iftrue force number of lines to 1 ***************************************/ if (autolines[section]) lines=1; if (dbug){ printf("Section number : %d\n", section+1); printf("Last bar in this section : %d\n", lastbarnumber); printf("Number of bars : %d\n", bars[section]); printf("Natural number of lines : %d\n", lines-mulooseness[section]); printf("Chosen number of lines : %d\n\n", lines);} if (dbug_logfile){ fprintf(logfile, "Section number : %d\n", section+1); fprintf(logfile, "Last bar in this section : %d\n", lastbarnumber); fprintf(logfile, "Number of bars : %d\n", bars[section]); fprintf(logfile, "Natural number of lines : %d\n", lines-mulooseness[section]); fprintf(logfile, "Chosen number of lines : %d\n\n", lines);} if (bars[section]<1) error_exit(3); /************************************************************** fill_length is the length of 'bar' material (ie excluding signature space) required to fill the remainder of the piece. This value will not be exact if there are sign changes within the section. However, fill_length is used only to keep track of the mean scale factor for the remainder of the piece, as opposed to individual lines. Loop over lines, working out number of bars and revised \elemskip for each line. added correct computing of fill_length ****************************************************************/ for (j=1; j<=lines; ++j, ++line_in_section){ ++line_number; fill_length=(lines-j+1)*(linewidth-(clefskip+signskip[sign])); /**************************************************** Work out mean element skip over remaining bars in the current section. EFFWID is the effective line width once key signature have been written. Set parindent to zero after it has been used for the first line of the first section. ****************************************************/ if (!eff_softlength[section]) error_exit(5); spc_factor=(fill_length-eff_hardlength[section])/eff_softlength[section]; eff_linewidth=linewidth-(clefskip+signskip[sign])-parindent; parindent=0; /**************************************************** Fill the current line by adding bars until overflow. *****************************************************/ i=mark; firstbarno=barno[mark+1]; hardlength= 0; softlength = 0; x = 0; detect_end= FALSE; while (x add to the first bar in next line the amount of afterruleskip *********************************************/ if (zbar[mark]){ softbarlength[i+1] += afterrule; eff_softlength[section] += afterrule;} /******************************************** last bar in line a leftrightrepeat? if true -> reduce hardwidth of current line advance the hardwidth of next bar advance the softwidth of next bar *********************************************/ if (lr_repeat[mark]){ /* printf("mark=%d\n",mark); printf("width_leftright=%f\n",width_leftrightrepeat[i]); printf("width_left=%f\n",width_leftrepeat[i]); */ hardlength -= (width_leftrightrepeat[i]-width_leftrepeat[i]); eff_hardlength[section] += (width_leftrightrepeat[i]-width_leftrepeat[i]); hardbarlength[i+1] += width_leftrepeat[i]; softbarlength[i+1] += afterrule/2; eff_softlength[section] += afterrule/2; } /******************************************** last bar in line a leftrepeat? if true -> reduce hardwidth of current line advance the hardwidth of next bar advance the softwidth of next bar *********************************************/ if (l_repeat[mark]){ hardlength -= (width_leftrepeat[i]-lthick); hardbarlength[i+1] += width_leftrepeat[i]; softbarlength[i+1] += afterrule/2; eff_softlength[section] += afterrule/2;} if (signchange[sign+1]==mark+1){ /* s.b. */ ++sign; hardlength += oldsignskip[sign]; hardbarlength[mark+1] -= oldsignskip[sign];}} /********************************************* Exclude the latest bar, and stretch the line. **********************************************/ else{ barsinline=i-1-mark; if (barsinline<1) error_exit(2); mark=i-1; lastbarno=barno[mark]; hardlength -= hardbarlength[i]; softlength -= softbarlength[i]; if (zbar[mark]) softbarlength[i] += afterrule; if (lr_repeat[mark]){ hardlength -= (width_leftrightrepeat[i-1]-width_leftrepeat[i-1]); eff_hardlength[section] += (width_leftrightrepeat[i-1]-width_leftrepeat[i-1]); hardbarlength[i] += width_leftrepeat[i-1]; softbarlength[i] += afterrule/2; eff_softlength[section] += afterrule/2;} if (l_repeat[mark]){ hardlength -= (width_leftrepeat[i-1]-lthick); hardbarlength[i] += width_leftrepeat[i-1]; softbarlength[i] += afterrule/2; eff_softlength[section] += afterrule/2;} /********************************************************************* Error (o/u-hbox) occurs only when signature change start in next line -> look for signature change in next line if true then advance the hardwidth of current line reduce next hard barlength by signature change **********************************************************************/ if (signchange[sign]==mark+1){ hardlength += oldsignskip[sign]; hardbarlength[mark+1] -= oldsignskip[sign];}} /*********************************************** Define a flex factor for this line as the ratio of soft part of the specified line width, to soft width in the approximate line. ************************************************/ if (!softlength) error_exit(5); flexit=(eff_linewidth-hardlength)/softlength; if (detectraggedline) {flexit=1; detectraggedline=FALSE;} cor_elemskip = elemskip * flexit; cor_afterrule = afterrule * flexit; cor_beforerule = beforerule * flexit; if (dbug){ printf("Line number : %d\n",line_number); printf("Fill length : %f\n",fill_length); printf("Effective length : %f\n", eff_softlength[section]+eff_hardlength[section]); printf("Mean space factor : %f\n",spc_factor); printf("Bars in line : %d\n",barsinline); printf("Effective linewidth : %f\n",eff_linewidth); printf("Uncorrected hard length : %f\n",hardlength); printf("Uncorrected soft length : %f\n",softlength); printf("Flex factor (soft) : %f\n",flexit); printf("Corrected elemskip : %f\n",cor_elemskip); printf("Corrected afterrule : %f\n",cor_afterrule); printf("Corrected beforerule : %f\n",cor_beforerule); getchar();} if (dbug_logfile){ fprintf(logfile, "Line number : %d\n",line_number); fprintf(logfile, "Fill length : %f\n",fill_length); fprintf(logfile, "Effective length : %f\n", eff_softlength[section]+eff_hardlength[section]); fprintf(logfile, "Mean space factor : %f\n",spc_factor); fprintf(logfile, "Bars in line : %d\n",barsinline); fprintf(logfile, "Effective linewidth : %f\n",eff_linewidth); fprintf(logfile, "Uncorrected hard length : %f\n",hardlength); fprintf(logfile, "Uncorrected soft length : %f\n",softlength); fprintf(logfile, "Flex factor (soft) : %f\n",flexit); fprintf(logfile, "Corrected elemskip : %f\n",cor_elemskip); fprintf(logfile, "Corrected afterrule : %f\n",cor_afterrule); fprintf(logfile, "Corrected beforerule : %f\n",cor_beforerule);} eff_hardlength[section] -= hardlength; eff_softlength[section] -= softlength; fill_length -= eff_linewidth; /********************************** Write a record to the output file. ***********************************/ fprintf( outfile, "\\lineset{%3d}{%2d}{%8.5fpt}{%8.5fpt}{%8.5fpt}%% %d - %d\n", line_number, barsinline, cor_elemskip, cor_afterrule, cor_beforerule, firstbarno, lastbarno); if (showresult){ printf( "\\lineset{%3d}{%2d}{%8.5fpt}{%8.5fpt}{%8.5fpt}%% %d - %d\n", line_number, barsinline, cor_elemskip, cor_afterrule, cor_beforerule, firstbarno, lastbarno);} if (dbug_lines) printf(" ... writing line : %d\r", line_number); if (dbug_logfile) fprintf(logfile, " ... writing line : %d\n", line_number); } /*eo for lines */ } /* eo for sections */ if (dbug_lines) printf("\n"); /********* <<<<<<<<< eo do **********/ samechapter=TRUE; ++chapterno; } while(GETLINE); /************* closing files **************/ fclose(infile); if (dbug_logfile){ fclose(logfile); if (!logfile) error_exit(0);} fclose(outfile); if (!outfile) error_exit(0); printf(" ... thats all, bye\n"); return(0); } /*** eof ***/