home *** CD-ROM | disk | FTP | other *** search
/ Languages Around the World / LanguageWorld.iso / language / japanese / win_prog / win_jwp / fileio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-31  |  49.6 KB  |  1,737 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5. #include "idm.h"
  6.  
  7.  
  8. #define HIGH_BIT_ESCAPE     0
  9.  
  10. #define MAXUNDOLEVELS       32000
  11.  
  12.  
  13. static struct {
  14.     char *name;
  15. } SupportedVersions[] = {
  16.     { "B1" },
  17.     { NULL }
  18. };
  19.  
  20. static char filename[MAXFILENAMELEN];
  21. static char filespec[MAXFILENAMELEN];
  22. static OFSTRUCT of;
  23. static FILE *Fp;
  24. static FILEOPTIONS *filep;
  25. static int FormatChoice;
  26. static BOOL ConvertLineBreaks, AlignKanjis, OutputLineBreaks;
  27. static int LineLength;
  28. static long int FileLength, StatusSteps, CharRead;
  29. static HWND statushwnd, statushwnd1;
  30.  
  31. static FILEFORMAT OriginalFormat;
  32. static char *OverwriteMessage;
  33.  
  34. static BOOL HasText, InWord;
  35. static int LineNumber;
  36. static int BlankSpaces, CharPosition;
  37. static int LastIndent, CurrentIndent, FirstIndent;
  38. static int LastChar;
  39. static BOOL LastTextIsKanji;
  40. static BOOL SkipHighBitWarnings;
  41. static int LevelsSaved = 0;
  42.  
  43. static POSITION p;
  44.  
  45.  
  46. char *FileExtensions[] = {
  47.     ".*",
  48.     ".JWP",
  49.     ".TPL",
  50.     ".EUC",
  51.     ".SJS",
  52.     ".JIS",
  53.     ".OLD",
  54.     ".NEC",
  55.     NULL
  56. };
  57.  
  58. char *FileFormatNames[] = {
  59.     "Auto-Detect",
  60.     "Normal",
  61.     "Template",
  62.     "EUC",
  63.     "Shift JIS",
  64.     "New JIS",
  65.     "Old JIS",
  66.     "NEC JIS",
  67.     NULL
  68. };
  69.  
  70. BOOL FAR PASCAL FileOpenDlgProc (HWND, WORD, WORD, LONG);
  71. BOOL FAR PASCAL FileSaveAsDlgProc (HWND, WORD, WORD, LONG);
  72. extern BOOL FAR PASCAL FileFindProc (HWND, WORD, WORD, LONG);
  73.  
  74.  
  75.  
  76. static void MoveStatusBar (long int percent)
  77. {
  78.     long int len;
  79.     char     buffer[10];
  80.     HWND     hwnd;
  81.     RECT     rect;
  82.     HDC      hdc;
  83.  
  84.     if (statushwnd == NULL) return;
  85.  
  86.     if (percent < 0L) return;
  87.     if (percent > 100L) percent = 100L;
  88.  
  89.     sprintf(buffer, "%ld%%", percent);
  90.     SetDlgItemText(statushwnd, 4204, buffer);
  91.  
  92.     hwnd = GetDlgItem(statushwnd, 4205);
  93.     GetClientRect(hwnd, &rect);
  94.     len = (rect.right - 4) * percent / 100L;
  95.  
  96.     hdc = GetDC(hwnd);
  97.     SelectObject(hdc, GetStockObject(GRAY_BRUSH));
  98.     Rectangle(hdc, 2, 2, len + 2, rect.bottom - 2);
  99.     ReleaseDC(hwnd, hdc);
  100. }
  101.  
  102.  
  103.  
  104. void NewParagraph (FILEOPTIONS *f, POSITION *pos, unsigned int n)
  105. {
  106.     POSITION p = *pos;
  107.     PARAGRAPH far *pp;
  108.     ONELINE far *lp;
  109.  
  110.  
  111.     if (PARAOF(p) == NULL) {
  112.         PARAOF(p) = f->paragraph = f->eof = pp = StructAlloc(PARAGRAPH);
  113.         pp->prev = pp->next = NULL;
  114.     } else {
  115.         PARAOF(p)->next = f->eof = pp = StructAlloc(PARAGRAPH);
  116.         pp->prev = PARAOF(p);
  117.         pp->next = NULL;
  118.         PARAOF(p) = pp;
  119.     }
  120.  
  121.     pp->leftindent = pp->firstindent = pp->rightindent = 0;
  122.  
  123.     if (pp->prev != NULL) {
  124.         pp->spacing = pp->prev->spacing;
  125.         pp->spacemulti = pp->prev->spacemulti;
  126.     } else {
  127.         pp->spacing = f->basefont->spacing;
  128.         pp->spacemulti = 100;
  129.     }
  130.     n *= TEXTBLOCKSIZE;
  131.     pp->text = (UNIT far *) BlockAlloc(n * sizeof(UNIT));
  132.     pp->textsize = n;
  133.     pp->text[0].kanji = '\0';
  134.  
  135.     LINEOF(p) = lp = pp->lines = pp->lastline = StructAlloc(ONELINE);
  136.     lp->next = lp->prev = NULL;
  137.     lp->position = 0;
  138.     lp->height = BASEFONT->height;
  139.     POSOF(p) = lp->length = 0;
  140.  
  141.     f->nr_lines++;
  142.  
  143.     LineNumber = 0;
  144.     *pos = p;
  145. }
  146.  
  147.  
  148.  
  149. static void WriteNormalFile (FILE *fp, FILEOPTIONS *f, int saveundo)
  150. {
  151.     int i, j, k;
  152.     UNIT far *cp;
  153.     PARAGRAPH far *pp;
  154.     FILEHEADER header;
  155.     FILEPARAHEADER pheader;
  156.     UNDOBUF far *up;
  157.  
  158.     memset(&header, 0, sizeof(FILEHEADER));
  159.     memset(&pheader, 0, sizeof(FILEPARAHEADER));
  160.  
  161.     header.magic = MAGIC;
  162.     strcpy(header.version, JWPFILEVERSION);
  163.     header.landscape = f->pagesetup.landscape ? 1 : 0;
  164.     header.paragraphs = 0;
  165.  
  166.     header.lrheader = f->lrheader;
  167.     header.nofirstpage = f->nofirstpage;
  168.  
  169.     for (i = 0; i < 4; i++) header.margins[i] = (float) f->pagesetup.margins[i];
  170.  
  171.     for (i = 0; i < NRSUMMARIES && f->summary[i] == NULL; i++);
  172.     if (i < NRSUMMARIES) header.summary = TRUE;
  173.  
  174.     for (j = 0; j < 4; j++) {
  175.         for (i = 0; i < NRHEADERS && f->header[j][i] == NULL; i++);
  176.         if (i < NRHEADERS) {
  177.             header.headers = TRUE;
  178.             break;
  179.         }
  180.     }
  181.  
  182.  
  183.     /* Undo's */
  184.  
  185.     if (saveundo != 0) {
  186.         if (saveundo < 0) saveundo = f->undolevels;
  187.  
  188.         for (i = 0, up = f->undo; up != NULL; up = up->next, i++);
  189.         f->undolevels = i;
  190.  
  191.         if (saveundo > f->undolevels) saveundo = f->undolevels;
  192.         header.undo = saveundo;
  193.     } else {
  194.         header.undo = 0;
  195.     }
  196.  
  197.  
  198.     /* How many paragraphs? */
  199.  
  200.     for (pp = f->paragraph; pp != NULL; pp = pp->next, header.paragraphs++);
  201.  
  202.     fwrite (&header, sizeof(FILEHEADER), 1, fp);
  203.  
  204.  
  205.     /* Summaries */
  206.  
  207.     if (header.summary) {
  208.         KANJI buffer[MAXLINELEN];
  209.  
  210.         for (i = 0; i < NRSUMMARIES; i++) {
  211.             if (f->summary[i] == NULL) {
  212.                 j = 0;
  213.                 fwrite(&j, sizeof(int), 1, fp);
  214.                 continue;
  215.             }
  216.  
  217.             j = kanjilen(f->summary[i]) + 1;
  218.             if (j >= MAXLINELEN) j = MAXLINELEN - 1;
  219.             fwrite(&j, sizeof(int), 1, fp);
  220.             kanjicpy(buffer, f->summary[i]);
  221.             fwrite(buffer, sizeof(KANJI), j, fp);
  222.         }
  223.     }
  224.  
  225.     /* Headers */
  226.  
  227.     if (header.headers) {
  228.         KANJI buffer[MAXLINELEN];
  229.  
  230.         for (k = 0; k < 4; k++) {
  231.             for (i = 0; i < NRHEADERS; i++) {
  232.                 if (f->header[k][i] == NULL) {
  233.                     j = 0;
  234.                     fwrite(&j, sizeof(int), 1, fp);
  235.                     continue;
  236.                 }
  237.  
  238.                 j = kanjilen(f->header[k][i]) + 1;
  239.                 if (j >= MAXLINELEN) j = MAXLINELEN - 1;
  240.                 fwrite(&j, sizeof(int), 1, fp);
  241.                 kanjicpy(buffer, f->header[k][i]);
  242.                 fwrite(buffer, sizeof(KANJI), j, fp);
  243.             }
  244.         }
  245.     }
  246.  
  247.     /* Undo's */
  248.  
  249.     if (saveundo > 0) {
  250.         unsigned int len;
  251.         PARAGRAPH far *pp;
  252.         char buffer[MAXLINELEN];
  253.  
  254.         for (i = 0, up = f->undo; i < saveundo && up != NULL; i++, up = up->next) {
  255.             _fmemcpy(buffer, up, sizeof(UNDOBUF));
  256.             fwrite(buffer, sizeof(UNDOBUF), 1, fp);
  257.  
  258.             switch (up->action) {
  259.                 case U_INSERT: break;
  260.                 case U_DELETE:
  261.                 case U_PARAFORMAT:
  262.                     for (pp = (PARAGRAPH far *) up->data; pp != NULL; pp = pp->next) {
  263.                         _fmemcpy(buffer, pp, sizeof(PARAGRAPH));
  264.                         fwrite(buffer, sizeof(PARAGRAPH), 1, fp);
  265.                         if (pp->text == NULL) {
  266.                             len = 0;
  267.                             fwrite(&len, sizeof(int), 1, fp);
  268.                         } else {
  269.                             len = unitlen(pp->text) + 1;
  270.                             fwrite(&len, sizeof(int), 1, fp);
  271.                             _fmemcpy(buffer, pp->text, len * sizeof(UNIT));
  272.                             fwrite(buffer, sizeof(UNIT), len, fp);
  273.                         }
  274.                     }
  275.                     break;
  276.             }
  277.         }
  278.     }
  279.  
  280.     /* Output the file */
  281.  
  282.     for (CharRead = 0L, pp = f->paragraph; pp != NULL; pp = pp->next) {
  283.  
  284.         pheader.textsize = unitlen(pp->text) + 1;
  285.         pheader.spacemulti = pp->spacemulti;
  286.         pheader.firstindent = pp->firstindent;
  287.         pheader.leftindent = pp->leftindent;
  288.         pheader.rightindent = pp->rightindent;
  289.         fwrite(&pheader, sizeof(FILEPARAHEADER), 1, fp);
  290.  
  291.         for (cp = pp->text; cp->kanji; cp++, CharRead++) {
  292.             if (CharRead % StatusSteps == 0)
  293.                 MoveStatusBar(CharRead / StatusSteps);
  294.  
  295.             if (ISKANJI(cp->kanji)) {
  296.                 fputc(HIBYTE(cp->kanji) | 0x0080, fp);
  297.                 fputc(LOBYTE(cp->kanji) | 0x0080, fp);
  298.             } else if (cp->kanji & 0x0080) {
  299.                 fputc(HIGH_BIT_ESCAPE, fp);
  300.                 fputc(cp->kanji & 0x007f, fp);
  301.             } else {
  302.                 fputc(cp->kanji & 0x007f, fp);
  303.             }
  304.         }
  305.  
  306.         fputc('\n', fp);
  307.     }
  308.  
  309.     MoveStatusBar(100L);
  310. }
  311.  
  312.  
  313.  
  314. static BOOL ReadNormalFile (FILE *fp, FILEOPTIONS *f, char * filename, HWND hwnd, BOOL template)
  315. {
  316.     unsigned int i, j, n;
  317.     int ch;
  318.     int len;
  319.     int version;
  320.     FILEHEADER header;
  321.     FILEPARAHEADER pheader;
  322.     POSITION p;
  323.  
  324.     fread (&header, sizeof(FILEHEADER), 1, fp);
  325.  
  326.     if (header.magic != MAGIC) {
  327.         ErrorMessage(global.hwnd, "%s is not a normal " PROGNAME " %s!",
  328.                         filename, template ? "template" : "file");
  329.         return (FALSE);
  330.     }
  331.  
  332.     /* Verify the version */
  333.  
  334.     if (!strcmp(header.version, JWPFILEVERSION)) {
  335.         version = -1;
  336.     } else {
  337.         for (i = 0; SupportedVersions[i].name != NULL; i++)
  338.             if (!strcmp(header.version, SupportedVersions[i].name)) break;
  339.  
  340.         if (SupportedVersions[i].name == NULL) {
  341.             ErrorMessage(hwnd, "%s is a %s created by an earlier version of "
  342.                                 PROGNAME ".  Unfortunately, it cannot be read by "
  343.                                 "the current version.  We are so very sorry...",
  344.                                 filename, template ? "template" : "file");
  345.             return (FALSE);
  346.         } else {
  347.             if (YesNo(hwnd, "%s is a %s created by an earlier version of " PROGNAME ".  %s",
  348.                             filename, template ? "template" : "file",
  349.                             template ? "Do you still want to use it?" :
  350.                                        "It can be read but will be overwritten "
  351.                                        "by the new format when you save it.  "
  352.                                        "Do you still want to open it?") != IDYES)
  353.                 return (FALSE);
  354.  
  355.             version = i;
  356.         }
  357.     }
  358.  
  359.     for (i = 0; i < 4; i++) f->pagesetup.margins[i] = (double) header.margins[i];
  360.     f->pagesetup.landscape = header.landscape;
  361.     f->lrheader = header.lrheader;
  362.     f->nofirstpage = header.nofirstpage;
  363.     f->linelen = CalcLineLength(f);
  364.  
  365.  
  366.     /* Any summary? */
  367.  
  368.     for (i = 0; i < NRSUMMARIES; i++) f->summary[i] = NULL;
  369.  
  370.     if (header.summary) {
  371.         KANJI buffer[MAXLINELEN];
  372.  
  373.         for (i = 0; i < NRSUMMARIES; i++) {
  374.             fread(&n, sizeof(int), 1, fp);
  375.             if (n > 0) {
  376.                 fread((char *) buffer, sizeof(KANJI), n, fp);
  377.                 f->summary[i] = (KANJI far *) BlockAlloc((n + 2) * sizeof(KANJI));
  378.                 kanjicpy(f->summary[i], buffer);
  379.             }
  380.         }
  381.     }
  382.  
  383.     /* Any headers? */
  384.  
  385.     for (j = 0; j < 4; j++) for (i = 0; i < NRHEADERS; i++) f->header[j][i] = NULL;
  386.  
  387.     if (header.headers) {
  388.         KANJI buffer[MAXLINELEN];
  389.  
  390.         for (j = 0; j < 4; j++) {
  391.             for (i = 0; i < NRHEADERS; i++) {
  392.                 fread(&n, sizeof(int), 1, fp);
  393.                 if (n > 0) {
  394.                     fread((char *) buffer, sizeof(KANJI), n, fp);
  395.                     f->header[j][i] = (KANJI far *) BlockAlloc((n + 2) * sizeof(KANJI));
  396.                     kanjicpy(f->header[j][i], buffer);
  397.                 }
  398.             }
  399.         }
  400.     }
  401.  
  402.  
  403.     /* Any undo chains? */
  404.  
  405.     f->undo = f->undotail = NULL;
  406.     f->undolevels = 0;
  407.  
  408.     if (!template && header.undo) {
  409.         unsigned int x, len;
  410.         UNIT ch;
  411.         UNDOBUF far *up = NULL, far *up1;
  412.         PARAGRAPH far *pp, far *pp1;
  413.         char buffer[MAXLINELEN];
  414.  
  415.         for (i = 0; i < header.undo; i++) {
  416.             fread(buffer, sizeof(UNDOBUF), 1, fp);
  417.  
  418.             if (up == NULL) {
  419.                 up1 = up = StructAlloc(UNDOBUF);
  420.                 _fmemcpy(up1, buffer, sizeof(UNDOBUF));
  421.                 up1->next = up1->prev = NULL;
  422.             } else {
  423.                 up1->next = StructAlloc(UNDOBUF);
  424.                 _fmemcpy(up1->next, buffer, sizeof(UNDOBUF));
  425.                 up1->next->prev = up1;
  426.                 up1 = up1->next;
  427.                 up1->next = NULL;
  428.             }
  429.  
  430.             f->undolevels++;
  431.  
  432.             switch (up1->action) {
  433.                 case U_INSERT: up1->data = NULL; break;
  434.                 case U_DELETE:
  435.                 case U_PARAFORMAT:
  436.                     pp = NULL;
  437.                     for (;;) {
  438.                         fread(buffer, sizeof(PARAGRAPH), 1, fp);
  439.  
  440.                         if (pp == NULL) {
  441.                             pp1 = pp = StructAlloc(PARAGRAPH);
  442.                             _fmemcpy(pp1, buffer, sizeof(PARAGRAPH));
  443.                             pp1->next = pp1->prev = NULL;
  444.                         } else {
  445.                             pp1->next = StructAlloc(PARAGRAPH);
  446.                             _fmemcpy(pp1->next, buffer, sizeof(PARAGRAPH));
  447.                             pp1->next->prev = pp1;
  448.                             pp1 = pp1->next;
  449.                             pp1->next = NULL;
  450.                         }
  451.  
  452.                         fread(&len, sizeof(unsigned int), 1, fp);
  453.                         if (len > 0) {
  454.                             pp1->text = (UNIT far *) BlockAlloc(len + 5);
  455.                             for (x = 0; x < len; x++) {
  456.                                 fread(&ch, sizeof(UNIT), 1, fp);
  457.                                 pp1->text[x] = ch;
  458.                             }
  459.                             pp1->text[len].kanji = 0;
  460.                         } else {
  461.                             pp1->text = NULL;
  462.                         }
  463.  
  464.                         if (pp1->next == NULL) break;
  465.                     }
  466.  
  467.                     up1->data = (void far *) pp;
  468.                     break;
  469.             }
  470.         }
  471.  
  472.         f->undo = up;
  473.         f->undotail = up1;
  474.  
  475.         TrimUndoChain(f);
  476.     }
  477.  
  478.     /* Read the file */
  479.  
  480.     PARAOF(p) = NULL;
  481.     LINEOF(p) = NULL;
  482.     POSOF(p) = 0;
  483.  
  484.     CharRead = 0L;
  485.  
  486.     for (i = 0; i < header.paragraphs; i++) {
  487.         OLDFILEPARAHEADER100 old1;
  488.  
  489.         switch (version) {
  490.             default:
  491.             case -1: fread(&pheader, sizeof(FILEPARAHEADER), 1, fp); break;
  492.             case 0:  fread(&old1, sizeof(OLDFILEPARAHEADER100), 1, fp);
  493.                      pheader.textsize = old1.textsize;
  494.                      pheader.firstindent = old1.firstindent;
  495.                      pheader.leftindent = old1.leftindent;
  496.                      pheader.rightindent = old1.rightindent;
  497.                      pheader.spacemulti = 100;
  498.                      break;
  499.         }
  500.  
  501.         len = pheader.textsize;
  502.         n = (len / TEXTBLOCKSIZE) + 1;
  503.  
  504.         NewParagraph(f, &p, n);
  505.  
  506.         PARAOF(p)->spacemulti = pheader.spacemulti;
  507.         PARAOF(p)->spacing = (f->basefont->height + f->basefont->spacing) * pheader.spacemulti / 100;
  508.         PARAOF(p)->spacing -= f->basefont->height;
  509.         PARAOF(p)->firstindent = pheader.firstindent;
  510.         PARAOF(p)->leftindent = pheader.leftindent;
  511.         PARAOF(p)->rightindent = pheader.rightindent;
  512.  
  513.         for (j = 0; j < len; j++) {
  514.             ch = fgetc(fp);
  515.  
  516.             if (ch & 0x0080) {      /* Kanji */
  517.                 PARAOF(p)->text[j].kanji = ((ch & 0x007f) << 8) | (fgetc(fp) & 0x007f);
  518.                 CharRead += 2L;
  519.             } else if (ch == HIGH_BIT_ESCAPE) {
  520.                 PARAOF(p)->text[j].kanji = fgetc(fp) | 0x0080;
  521.                 CharRead += 2L;
  522.             } else {
  523.                 PARAOF(p)->text[j].kanji = ch;
  524.                 CharRead++;
  525.             }
  526.             f->nr_bytes++;
  527.             if (StatusSteps > 0 && CharRead % StatusSteps == 0)
  528.                 MoveStatusBar(CharRead / StatusSteps);
  529.         }
  530.         PARAOF(p)->text[len-1].kanji = 0;
  531.         LINEOF(p)->length = len-1;
  532.     }
  533.  
  534.     MoveStatusBar(100L);
  535.     return (TRUE);
  536. }
  537.  
  538.  
  539.  
  540. static int OpenCharIn (void)
  541. {
  542.     long int percent;
  543.     int ch;
  544.  
  545.     ch = fgetc(Fp);
  546.  
  547.     if (statushwnd == NULL) return (ch);
  548.  
  549.     CharRead++;
  550.  
  551.     if (CharRead % StatusSteps == 0 || ch == EOF) {
  552.         percent = CharRead / StatusSteps;
  553.         if (ch == EOF || CharRead >= FileLength) percent = 100L;
  554.  
  555.         MoveStatusBar(percent);
  556.     }
  557.  
  558.     return (ch);
  559. }
  560.  
  561.  
  562. static void OpenCharOut (int ch)
  563. {
  564.     int i, j;
  565.     KANJI k;
  566.     KANJI buf[10];
  567.  
  568.  
  569.     if (ch == '\r') return;         /* Ignore */
  570.  
  571.     /* Leading spaces */
  572.  
  573.     if (ch <= ' ' && ch != '\n') {
  574.         if (!HasText) {
  575.             CurrentIndent++;
  576.         } else {
  577.             BlankSpaces++;
  578.         }
  579.         return;
  580.     }
  581.  
  582.     if (ch == '\n') {
  583.         CurrentIndent = 0;
  584.         LineNumber++;
  585.  
  586.         if (!ConvertLineBreaks) {
  587.             NewParagraph(filep, &p, 1);
  588.             FirstIndent = LastIndent = 0;
  589.             LineNumber = 0;
  590.         } else if (!HasText) {             /* Blank line */
  591.             NewParagraph(filep, &p, 1);
  592.             FirstIndent = LastIndent = -1;
  593.             LineNumber = 2;
  594.         }
  595.  
  596.         BlankSpaces = 0;
  597.  
  598.         HasText = FALSE;
  599.         return;
  600.     }
  601.  
  602.     /* Check indents */
  603.  
  604.     if (!HasText) {
  605.         switch (LineNumber) {
  606.             case 0:
  607.                 /* No need to check the first line */
  608.                 FirstIndent = LastIndent = CurrentIndent;
  609.                 PARAOF(p)->firstindent = PARAOF(p)->leftindent = FirstIndent / 2;
  610.                 break;
  611.  
  612.             case 1:
  613.                 /* The second line */
  614.                 LastIndent = CurrentIndent;
  615.                 PARAOF(p)->leftindent = LastIndent / 2;
  616.                 break;
  617.  
  618.             default:
  619.                 /* The rest */
  620.                 if (LastIndent != CurrentIndent) {
  621.                     NewParagraph(filep, &p, 1);
  622.  
  623.                     FirstIndent = LastIndent = CurrentIndent;
  624.                     PARAOF(p)->firstindent = PARAOF(p)->leftindent = FirstIndent / 2;
  625.                 }
  626.                 break;
  627.         }
  628.     }
  629.  
  630.  
  631.     /* Take care of the blank spaces */
  632.  
  633.     if (BlankSpaces > 0) {
  634.         j = (BlankSpaces + 1) / 2;
  635.  
  636.         if (!HasText) {
  637.             k = 0x2121;
  638.         } else if (!LastTextIsKanji && (ch & 0x80)) {
  639.             if (AlignKanjis) {
  640.                 j = 1;
  641.                 k = '\t';
  642.             } else {
  643.                 j = BlankSpaces;
  644.                 k = ' ';
  645.             }
  646.         } else if (LastTextIsKanji && !(ch & 0x80)) {
  647.             j = BlankSpaces;
  648.             k = ' ';
  649.         } else if (!LastTextIsKanji && !(ch & 0x80)) {
  650.             j = BlankSpaces;
  651.             k = ' ';
  652.         } else {
  653.             k = 0x2121;
  654.         }
  655.  
  656.         buf[0] = k;
  657.         buf[1] = 0;
  658.         for (i = 0; i < j; i++, POSOF(p)++) InsertString (filep, p, buf, 0);
  659.  
  660.         BlankSpaces = 0;
  661.     }
  662.  
  663.  
  664.     /* Insert the character */
  665.  
  666.     i = 0;
  667.  
  668.     if (LastChar != 0) {
  669.         if (!HasText && LineNumber > 0 && !LastTextIsKanji) buf[i++] = ' ';
  670.         if (ch & 0x80) {
  671.             buf[i++] = (LastChar << 8) | (ch & 0x7f);
  672.             LastChar = 0;
  673.             LastTextIsKanji = TRUE;
  674.         } else {
  675.             buf[i++] = LastChar;
  676.             buf[i++] = ch;
  677.             LastChar = 0;
  678.             LastTextIsKanji = FALSE;
  679.         }
  680.     } else if (ch & 0x80) {
  681.         LastChar = (ch & 0x7f);
  682.         return;
  683.     } else {
  684.         if (!HasText && LineNumber > 0) buf[i++] = ' ';
  685.         buf[i++] = ch;
  686.         LastTextIsKanji = FALSE;
  687.     }
  688.  
  689.     buf[i] = 0;
  690.  
  691.     InsertString (filep, p, buf, 0);
  692.     HasText = TRUE;
  693.     BlankSpaces = 0;
  694.  
  695.     POSOF(p) += i;
  696. }
  697.  
  698.  
  699.  
  700. BOOL DoFileOpen (char *pathname)
  701. {
  702.     int         fd;
  703.     FILEFORMAT  incode;
  704.     HCURSOR     hCursor;
  705.     FILEOPTIONS *ToClose = NULL;
  706.     char        buffer[256];
  707.  
  708.  
  709.     /* Is this the first file opened? */
  710.  
  711.     if (fileoptions != NULL && fileoptions->next == NULL && !fileoptions->changed) {
  712.         GetWindowText(fileoptions->parent, buffer, 256);
  713.         if (!strcmp(buffer, "Untitled #1")) ToClose = fileoptions;
  714.     }
  715.  
  716.  
  717.     if (pathname == NULL) {
  718.         if (!DialogBox(hInstance, "FileOpen", global.hwnd, FileOpenDlgProc)) {
  719.             return (FALSE);
  720.         }
  721.     } else {
  722.         strcpy(filename, pathname);
  723.         FormatChoice = FF_UNKNOWN;
  724.     }
  725.  
  726.     hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  727.     ShowCursor(TRUE);
  728.  
  729.     incode = (FILEFORMAT) FormatChoice;
  730.  
  731.     LastIndent = CurrentIndent = FirstIndent = LastChar = 0;
  732.     LineNumber = BlankSpaces = 0;
  733.     HasText = FALSE;
  734.     LastTextIsKanji = TRUE;
  735.  
  736.     fd = OpenFile(filename, &of, OF_READ);
  737.     if (fd < 0) return (FALSE);
  738.  
  739.     /* Normal format? */
  740.  
  741.     if (incode == FF_UNKNOWN) {
  742.         unsigned long int magic;
  743.  
  744.         lseek(fd, 0L, 0);
  745.         read(fd, &magic, sizeof(unsigned long int));
  746.         lseek(fd, 0L, 0);
  747.  
  748.         if (magic == MAGIC) incode = FF_NORMAL;
  749.     }
  750.  
  751.  
  752.     Fp = fdopen(fd, "r");
  753.     if (Fp == NULL) {
  754.         close(fd);
  755.         return (FALSE);
  756.     }
  757.  
  758.  
  759.     SetupIO(OpenCharIn, OpenCharOut);
  760.  
  761.     fseek(Fp, 0L, 2);
  762.     FileLength = ftell(Fp);
  763.     StatusSteps = (FileLength / 100L) + 1L;
  764.     CharRead = 0L;
  765.  
  766.     fseek(Fp, 0L, 0);
  767.  
  768.  
  769.     /* Open the status dialog box */
  770.  
  771.     statushwnd1 = CreateDialog(hInstance, "FileStatus", 0, NULL);
  772.     SetDlgItemText(statushwnd1, 4201, "Reading File:");
  773.     sprintf(buffer, "%s  (%0.2fK)", filename, (double) FileLength / 1024.0);
  774.     SetDlgItemText(statushwnd1, 4202, buffer);
  775.     SetDlgItemText(statushwnd1, 4203, "Determining File Format...");
  776.     SetDlgItemText(statushwnd1, 4204, "0%");
  777.  
  778.     statushwnd = NULL;
  779.     if (incode == FF_UNKNOWN) {
  780.         incode = DetectCodeType();
  781.         if (incode == FF_UNKNOWN) {
  782.             if (YesNo(statushwnd1, "The file %s is not in any of the "
  783.                       "supported Japanese text formats.  Open it anyway?", filename) != IDYES) {
  784.                 fclose(Fp);
  785.                 DestroyWindow(statushwnd1);
  786.                 statushwnd1 = NULL;
  787.                 return (FALSE);
  788.             }
  789.         }
  790.         fseek(Fp, 0L, 0);
  791.     }
  792.  
  793.     sprintf(buffer, "File Format: %s", (incode == FF_UNKNOWN) ? "Unknown" : FileFormatNames[incode]);
  794.     statushwnd = statushwnd1;
  795.     SetDlgItemText(statushwnd, 4203, buffer);
  796.  
  797.  
  798.     filep = NewFile(FN_NORMAL, (incode != FF_NORMAL && incode != FF_TEMPLATE));
  799.     if (filep == NULL) {
  800.         fclose(Fp);
  801.         ErrorMessage(global.hwnd, "Cannot open any more file window!");
  802.         DestroyWindow(statushwnd);
  803.         statushwnd = NULL;
  804.         return (FALSE);
  805.     }
  806.  
  807.     if (incode == FF_NORMAL || incode == FF_TEMPLATE) {
  808.         strcpy(filep->filename, of.szPathName);
  809.  
  810.         if (!ReadNormalFile(Fp, filep, filep->filename, statushwnd, FALSE)) {
  811.             FILEOPTIONS *f1;
  812.  
  813.             fclose(Fp);
  814.             DestroyWindow(statushwnd);
  815.             statushwnd = NULL;
  816.  
  817.             ShowCursor(FALSE);
  818.             SetCursor(hCursor);
  819.  
  820.             CloseFile(filep);
  821.  
  822.             /* Unlink it */
  823.  
  824.             if (fileoptions == filep) {
  825.                 fileoptions = filep->next;
  826.             } else {
  827.                 for (f1 = fileoptions; f1 != NULL && f1->next != filep; f1 = f1->next);
  828.                 if (f1 == NULL) {
  829.                     ErrorMessage(global.hwnd, "Funny: cannot find FILEOPTIONS record to deallocate");
  830.                 } else {
  831.                     f1->next = filep->next;
  832.                 }
  833.             }
  834.             return (FALSE);
  835.         }
  836.     } else {
  837.         filep->filename[0] = '\0';
  838.  
  839.         PARAOF(p) = filep->paragraph;
  840.         LINEOF(p) = filep->paragraph->lines;
  841.         POSOF(p) = 0;
  842.  
  843.         FileImport(incode);
  844.     }
  845.  
  846.     fclose(Fp);
  847.  
  848.  
  849.  
  850.     /* Reformat */
  851.  
  852.     SetDlgItemText(statushwnd1, 4201, "Reformatting...");
  853.  
  854.     TOPPARA(filep) = CURPARA(filep) = filep->paragraph;
  855.     TOPLINE(filep) = CURLINE(filep) = filep->paragraph->lines;
  856.     CURCHAR(filep) = 0;
  857.  
  858.     ReformatFile(filep);
  859.  
  860.     DestroyWindow(statushwnd);
  861.     statushwnd = NULL;
  862.  
  863.  
  864.     if (incode != FF_UNKNOWN && incode != FF_NORMAL && incode != FF_TEMPLATE) {
  865.         filep->fileformat = incode;
  866.         sprintf(buffer, "%s (%s)", filename, FileFormatNames[incode]);
  867.     } else {
  868.         strcpy(buffer, filename);
  869.     }
  870.     strcpy(filep->filename, filename);
  871.     ShowFileWindow(buffer, filep);
  872.  
  873.  
  874.     if (ToClose != NULL) {
  875.         ToClose->changed = FALSE;
  876.         SendMessage(global.clienthwnd, WM_MDIDESTROY, ToClose->parent, 0L);
  877.     }
  878.  
  879.     ShowCursor(FALSE);
  880.     SetCursor(hCursor);
  881.  
  882.     filep->changed = FALSE;
  883.  
  884.     PutQuickFile(of.szPathName);
  885.     UpdateQuickFiles();
  886.  
  887.     return (TRUE);
  888. }
  889.  
  890.  
  891.  
  892. FILEOPTIONS *CreateUsingTemplate (char far *tpl, int Untitled)
  893. {
  894.     int fd;
  895.     FILE *Fp;
  896.     OFSTRUCT of;
  897.     FILEOPTIONS *f, *ToClose;
  898.     char buffer[MAXLINELEN];
  899.  
  900.     /* Is this the first file opened? */
  901.  
  902.     if (fileoptions != NULL && fileoptions->next == NULL && !fileoptions->changed) {
  903.         GetWindowText(fileoptions->parent, buffer, 256);
  904.         if (!strcmp(buffer, "Untitled #1")) ToClose = fileoptions;
  905.     }
  906.  
  907.  
  908.     fd = OpenFile(tpl, &of, OF_READ);
  909.     if (fd < 0) return (NULL);
  910.  
  911.     Fp = fdopen(fd, "r");
  912.     if (Fp == NULL) {
  913.         close(fd);
  914.         return (NULL);
  915.     }
  916.  
  917.     fseek(Fp, 0L, 0);
  918.  
  919.     f = NewFile(FN_NORMAL, FALSE);
  920.     if (f == NULL) {
  921.         fclose(Fp);
  922.         ErrorMessage(global.hwnd, "Cannot open any more file window!");
  923.         return (NULL);
  924.     }
  925.  
  926.     statushwnd = NULL;
  927.     StatusSteps = 0L;
  928.  
  929.     if (!ReadNormalFile(Fp, f, "This", global.hwnd, TRUE)) {
  930.         FILEOPTIONS *f1;
  931.  
  932.         fclose(Fp);
  933.         CloseFile(f);
  934.  
  935.         /* Unlink it */
  936.  
  937.         if (fileoptions == f) {
  938.             fileoptions = f->next;
  939.         } else {
  940.             for (f1 = fileoptions; f1 != NULL && f1->next != f; f1 = f1->next);
  941.             if (f1 == NULL) {
  942.                 ErrorMessage(global.hwnd, "Funny: cannot find FILEOPTIONS record to deallocate");
  943.             } else {
  944.                 f1->next = f->next;
  945.             }
  946.         }
  947.         return (NULL);
  948.     }
  949.  
  950.     close(fd);
  951.  
  952.     TOPPARA(f) = CURPARA(f) = f->paragraph;
  953.     TOPLINE(f) = CURLINE(f) = f->paragraph->lines;
  954.     CURCHAR(f) = 0;
  955.  
  956.     ReformatFile(f);
  957.  
  958.     f->fileformat = FF_NORMAL;
  959.     sprintf(buffer, "Untitled #%d", Untitled);
  960.     ShowFileWindow(buffer, f);
  961.  
  962.     f->changed = FALSE;
  963.  
  964.     if (ToClose != NULL) {
  965.         ToClose->changed = FALSE;
  966.         SendMessage(global.clienthwnd, WM_MDIDESTROY, ToClose->parent, 0L);
  967.     }
  968.     return (f);
  969. }
  970.  
  971.  
  972.  
  973. static int SaveCharIn (void)
  974. {
  975.     int i;
  976.     KANJI ch, temp;
  977.     long int percent;
  978.     HWND hwnd;
  979.  
  980.     if (LastChar != 0) {
  981.         ch = LastChar;
  982.         LastChar = 0;
  983.         CharPosition++;
  984.         return (ch);
  985.     } else if (PARAOF(p) == NULL || LINEOF(p) == NULL) {
  986.         ch = EOF;
  987.         goto StatusBar;     /* Put the bar to 100% */
  988.     } if (OutputLineBreaks && !HasText && CharPosition <
  989.             (LineNumber ? PARAOF(p)->leftindent : PARAOF(p)->firstindent) * 2) {
  990.         CharPosition++;
  991.         return (' ');
  992.     } else if (OutputLineBreaks && CharPosition >= LineLength - PARAOF(p)->rightindent) {
  993.         HasText = InWord = FALSE;
  994.         CharPosition = 0;
  995.         LineNumber++;
  996.         return ('\n');
  997.     }
  998.  
  999.  
  1000.     for (;;) {
  1001.         ch = (CHAROF(p, POSOF(p)) & 0x7fff);
  1002.         if (ISKANJI(ch)) ch &= 0x7f7f;
  1003.  
  1004.         if (!ch) {
  1005.             POSOF(p) = 0;
  1006.             PARAOF(p) = PARAOF(p)->next;
  1007.             if (PARAOF(p) != NULL) LINEOF(p) = PARAOF(p)->lines;
  1008.             else LINEOF(p) = NULL;
  1009.  
  1010.             HasText = InWord = FALSE;
  1011.             CharPosition = LineNumber = 0;
  1012.             return ('\n');
  1013.         }
  1014.  
  1015.         if (!HasText && (ch <= ' ' || ch == 0x2121)) {
  1016.             POSOF(p)++;
  1017.             CharRead++;
  1018.             continue;
  1019.         }
  1020.  
  1021.         if (ISKANJI(ch)) {
  1022.             if (ch == 0x2121) {
  1023.                 ch = LastChar = ' ';
  1024.             } else {
  1025.                 LastChar = (LOBYTE(ch) | 0x80);
  1026.                 ch = (HIBYTE(ch) | 0x80);
  1027.             }
  1028.             InWord = FALSE;
  1029.         } else if (ch <= ' ') {
  1030.             ch = ' ';
  1031.             InWord = FALSE;
  1032.         } else {
  1033.             if (!SkipHighBitWarnings && ch & 0x80) {
  1034.                 if (statushwnd == NULL) hwnd = global.hwnd; else hwnd = statushwnd;
  1035.  
  1036.                 if (YesNo(hwnd, "This file contains "
  1037.                                 "the extended ASCII character '%c'.  "
  1038.                                 "Unfortunately, the file format you have "
  1039.                                 "chosen does not support extended ASCII "
  1040.                                 "characters.  "
  1041.                                 "The high-bit of this character will "
  1042.                                 "be lost in the saved file, and it will "
  1043.                                 "become '%c'.\n\n"
  1044.                                 "Do you want to continue reporting "
  1045.                                 "other extended ASCII characters?",
  1046.                                 ch, ch & 0x7f) == IDNO)
  1047.                     SkipHighBitWarnings = TRUE;
  1048.             }
  1049.  
  1050.             ch &= 0x7f7f;
  1051.  
  1052.             if (strchr("-", ch) != NULL) {
  1053.                 InWord = FALSE;
  1054.             } else {
  1055.                 if (!InWord) {          /* Search for word break */
  1056.                     for (i = 1; ; i++) {
  1057.                         temp = CHAROF(p, POSOF(p)+i);
  1058.                         if (!temp) break;
  1059.                         if (IsSmallKana(temp)) break;
  1060.                         if (temp <= ' ' || strchr("-", temp) != NULL) break;
  1061.  
  1062.                         if (OutputLineBreaks && CharPosition + i >= LineLength - PARAOF(p)->rightindent) {
  1063.                             HasText = InWord = FALSE;
  1064.                             CharPosition = 0;
  1065.                             LineNumber++;
  1066.                             return ('\n');
  1067.                         }
  1068.                     }
  1069.                 }
  1070.                 InWord = TRUE;
  1071.             }
  1072.         }
  1073.  
  1074.         break;
  1075.     }
  1076.  
  1077.     POSOF(p)++;
  1078.     CharPosition++;
  1079.     HasText = TRUE;
  1080.  
  1081.     if (statushwnd == NULL) return (ch);
  1082.  
  1083.     CharRead++;
  1084.  
  1085. StatusBar:
  1086.  
  1087.     if (CharRead % StatusSteps == 0 || ch == EOF) {
  1088.         percent = CharRead / StatusSteps;
  1089.         if (ch == EOF || CharRead >= FileLength) percent = 100L;
  1090.  
  1091.         MoveStatusBar(percent);
  1092.     }
  1093.     return (ch);
  1094. }
  1095.  
  1096.  
  1097.  
  1098. static void SaveCharOut (int ch)
  1099. {
  1100.     fputc(ch, Fp);
  1101. }
  1102.  
  1103.  
  1104.  
  1105. BOOL FAR PASCAL FileSaveFormatProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1106. {
  1107.     switch (message) {
  1108.         case WM_INITDIALOG: {
  1109.             char buffer[100];
  1110.  
  1111.             sprintf(buffer, OverwriteMessage, filename, FileFormatNames[OriginalFormat]);
  1112.             SetDlgItemText(hwnd, 4211, buffer);
  1113.             SetDlgItemText(hwnd, 4201, FileFormatNames[OriginalFormat]);
  1114.             CenterDialogBox(hwnd);
  1115.             return (TRUE);
  1116.         }
  1117.  
  1118.         case WM_COMMAND:
  1119.             switch (wParam) {
  1120.                 case IDOK:      OriginalFormat = FF_NORMAL;
  1121.                                 EndDialog(hwnd, TRUE);
  1122.                                 return (TRUE);
  1123.  
  1124.                 case IDCANCEL:  OriginalFormat = FF_UNKNOWN;
  1125.                                 EndDialog(hwnd, TRUE);
  1126.                                 return (TRUE);
  1127.  
  1128.                 case 4201:      EndDialog(hwnd, TRUE);
  1129.                                 return (TRUE);
  1130.  
  1131.                 default:        break;
  1132.             }
  1133.             break;
  1134.     }
  1135.  
  1136.     return (FALSE);
  1137. }
  1138.  
  1139.  
  1140.  
  1141. BOOL DoFileSaveAs (BOOL Dialog)
  1142. {
  1143.     int         fd;
  1144.     int         i, olddrive;
  1145.     FILEFORMAT  outcode;
  1146.     HCURSOR     hCursor;
  1147.     char        buffer[MAXLINELEN];
  1148.     char        olddir[MAXLINELEN];
  1149.  
  1150.     if (global.active == NULL) return (FALSE);
  1151.  
  1152.     filep = global.active;
  1153.  
  1154.     if (Dialog || !filep->filename[0]) {
  1155.         if (!DialogBox(hInstance, "FileSaveAs", global.hwnd, FileSaveAsDlgProc)) {
  1156.             return (FALSE);
  1157.         }
  1158.         outcode = (FILEFORMAT) FormatChoice + FF_NORMAL;
  1159.  
  1160.         if (outcode == FF_NORMAL)
  1161.             SendMessage(global.hwnd, WM_COMMAND, IDM_FILESUMMARY, 0L);
  1162.     } else if (filep->fileformat != FF_NORMAL && filep->fileformat != FF_TEMPLATE) {
  1163.         BOOL same;
  1164.  
  1165.         strcpy(filename, filep->filename);
  1166.  
  1167.         /* Change the extension to .JWP */
  1168.  
  1169.         for (i = strlen(filename) - 1; i >= 0; i--) {
  1170.             if (filename[i] == '\\' || filename[i] == '/' ||
  1171.                 filename[i] == '.' || filename[i] == ':') break;
  1172.         }
  1173.  
  1174.         if (i < 0 || filename[i] != '.') {
  1175.             strcat(filename, FileExtensions[1]);    /* Normal extension */
  1176.             same = FALSE;
  1177.         } else if (!strncpy(filename + i, FileExtensions[1], 4)) {
  1178.             same = TRUE;
  1179.         } else {
  1180.             strcpy(filename + i, FileExtensions[1]);
  1181.             same = FALSE;
  1182.         }
  1183.  
  1184.  
  1185.         /* Overwrite with normal format? */
  1186.  
  1187.         OriginalFormat = filep->fileformat;
  1188.  
  1189.         if (!same) OverwriteMessage = "Save file as %s (Normal Format)?\nOr keep it %s?";
  1190.         else OverwriteMessage = "Overwrite %s with Normal Format?\nOr keep it %s?";
  1191.  
  1192.         MessageBeep(0);
  1193.  
  1194.         DialogBox(hInstance, "FileSaveFormat", global.hwnd, FileSaveFormatProc);
  1195.  
  1196.         if (OriginalFormat == FF_UNKNOWN) return (FALSE);
  1197.  
  1198.         if (OriginalFormat != FF_NORMAL) strcpy(filename, filep->filename);
  1199.  
  1200.         outcode = OriginalFormat;
  1201.         FormatChoice = outcode - FF_NORMAL;
  1202.  
  1203.         if (outcode == FF_NORMAL)
  1204.             SendMessage(global.hwnd, WM_COMMAND, IDM_FILESUMMARY, 0L);
  1205.     } else {
  1206.         strcpy(filename, filep->filename);
  1207.         outcode = filep->fileformat;
  1208.         FormatChoice = outcode - FF_NORMAL;
  1209.     }
  1210.  
  1211.     /* Template? */
  1212.  
  1213.     if (outcode == FF_TEMPLATE) {
  1214.         if (filep->summary[0] == NULL) {    /* No title */
  1215.             ErrorMessage(global.hwnd, "You must provide a Title for this template.");
  1216.             return (FALSE);
  1217.         }
  1218.  
  1219.         /* Switch to the JWP directory */
  1220.  
  1221.         getcwd(olddir, MAXLINELEN);
  1222.         if (global.jwppath[0] - 'A' != getdisk()) {
  1223.             olddrive = getdisk();
  1224.             setdisk(global.jwppath[0] - 'A');
  1225.         } else {
  1226.             olddrive = -1;
  1227.         }
  1228.  
  1229.         _fstrcpy(buffer, global.jwppath);
  1230.         i = strlen(buffer);
  1231.         if (i > 3) buffer[i-1] = '\0';
  1232.  
  1233.         if (chdir(buffer) < 0) {
  1234.             ErrorMessage(global.hwnd, "Cannot switch to the " PROGNAME " directory!");
  1235.             if (olddrive >= 0) setdisk(olddrive);
  1236.             return (FALSE);
  1237.         }
  1238.     }
  1239.  
  1240.  
  1241.     /* Now save the file */
  1242.  
  1243.     hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1244.     ShowCursor(TRUE);
  1245.  
  1246.     LineNumber = LastChar = CharPosition = 0;
  1247.     HasText = InWord = FALSE;
  1248.  
  1249.     fd = OpenFile(filename, &of, OF_WRITE | OF_CREATE);
  1250.     if (fd < 0) return (FALSE);
  1251.  
  1252.     if (outcode == FF_NORMAL || outcode == FF_TEMPLATE) {
  1253.         Fp = fdopen(fd, "wb");
  1254.     } else {
  1255.         Fp = fdopen(fd, "wt");
  1256.     }
  1257.     if (Fp == NULL) {
  1258.         close(fd);
  1259.         return (FALSE);
  1260.     }
  1261.  
  1262.     SetupIO(SaveCharIn, SaveCharOut);
  1263.  
  1264.     FileLength = 0;
  1265.     StatusSteps = (FileLength / 100L) + 1L;
  1266.     CharRead = 0L;
  1267.  
  1268.     fseek(Fp, 0L, 0);
  1269.  
  1270.     /* Open the status dialog box */
  1271.  
  1272.     statushwnd = CreateDialog(hInstance, "FileStatus", 0, NULL);
  1273.     SetDlgItemText(statushwnd, 4201, "Writing File:");
  1274.     SetDlgItemText(statushwnd, 4202, filename);
  1275.     sprintf(buffer, "File Format: %s", FileFormatNames[outcode]);
  1276.     SetDlgItemText(statushwnd, 4203, buffer);
  1277.     SetDlgItemText(statushwnd, 4204, "0%");
  1278.  
  1279.  
  1280.     CharRead = 0L;
  1281.     FileLength = filep->nr_bytes;
  1282.  
  1283.     StatusSteps = (FileLength / 100L) + 1L;
  1284.  
  1285.  
  1286.     if (outcode == FF_NORMAL) {
  1287.         WriteNormalFile(Fp, filep, global.saveundolevels);
  1288.     } else if (outcode == FF_TEMPLATE) {
  1289.         WriteNormalFile(Fp, filep, 0);
  1290.     } else {
  1291.         PARAOF(p) = filep->paragraph;
  1292.         LINEOF(p) = filep->paragraph->lines;
  1293.         POSOF(p) = 0;
  1294.  
  1295.         SkipHighBitWarnings = FALSE;
  1296.         FileExport(outcode);
  1297.     }
  1298.  
  1299.     fclose(Fp);
  1300.  
  1301.     strcpy(filep->filename, filename);
  1302.     filep->fileformat = outcode;
  1303.  
  1304.     if (outcode != FF_NORMAL && outcode != FF_TEMPLATE) {
  1305.         sprintf(buffer, "%s (%s)", filep->filename, FileFormatNames[outcode]);
  1306.     } else {
  1307.         strcpy(buffer, filep->filename);
  1308.     }
  1309.     SetWindowText(filep->parent, buffer);
  1310.  
  1311.     DestroyWindow(statushwnd);
  1312.     statushwnd = NULL;
  1313.  
  1314.     if (outcode == FF_TEMPLATE) {
  1315.         if (olddrive >= 0) setdisk(olddrive);
  1316.         chdir(olddir);
  1317.     }
  1318.  
  1319.     ShowCursor(FALSE);
  1320.     SetCursor(hCursor);
  1321.  
  1322.     filep->changed = FALSE;
  1323.  
  1324.     PutQuickFile(of.szPathName);
  1325.     UpdateQuickFiles();
  1326.  
  1327.     return (TRUE);
  1328. }
  1329.  
  1330.  
  1331.  
  1332. BOOL FAR PASCAL FileOpenDlgProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1333. {
  1334.     int i, j;
  1335.  
  1336.  
  1337.     switch (message) {
  1338.  
  1339.     case WM_INITDIALOG:
  1340.         strcpy(filename,"*.*");
  1341.         strcpy(filespec,"*.*");
  1342.  
  1343.         SendDlgItemMessage(hwnd, 4201, EM_LIMITTEXT, MAXFILENAMELEN, 0L);
  1344.         SendDlgItemMessage(hwnd, 4202, EM_LIMITTEXT, MAXFILENAMELEN, 0L);
  1345.  
  1346.         DlgDirList(hwnd, filespec, 4211, 4202, 0x0000);
  1347.         DlgDirList(hwnd, "*.*", 4212, 4202, 0xc010);
  1348.  
  1349.         SetDlgItemText(hwnd, 4201, filespec);
  1350.  
  1351.         for (i = 0; FileFormatNames[i] != NULL; i++)
  1352.             SendDlgItemMessage(hwnd, 4221, CB_INSERTSTRING, -1, (LONG) ((LPSTR) FileFormatNames[i]));
  1353.         SendDlgItemMessage(hwnd, 4221, CB_SETCURSEL, 0, 0L);
  1354.  
  1355.         CheckDlgButton (hwnd, 4222, FALSE);
  1356.         CheckDlgButton (hwnd, 4223, TRUE);
  1357.  
  1358.         CenterDialogBox(hwnd);
  1359.  
  1360.         return (TRUE);
  1361.  
  1362.     case WM_CHAR:
  1363.         switch (wParam) {
  1364.             case '\x1b': SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
  1365.                          return (TRUE);
  1366.         }
  1367.         break;
  1368.  
  1369.     case WM_COMMAND:
  1370.         switch (wParam) {
  1371.             case 4211:
  1372.                 switch (HIWORD(lParam)) {
  1373.                     case LBN_SELCHANGE:
  1374.                     case LBN_DBLCLK:
  1375.                         DlgDirSelect(hwnd, filename, 4211);
  1376.                         SetDlgItemText(hwnd, 4201, filename);
  1377.                         if (HIWORD(lParam) == LBN_DBLCLK)
  1378.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1379.                         return (TRUE);
  1380.                 }
  1381.                 break;
  1382.  
  1383.             case 4212: {
  1384.                 char directory[MAXFILENAMELEN];
  1385.  
  1386.                 switch (HIWORD(lParam)) {
  1387.                     case LBN_DBLCLK:
  1388.                         DlgDirSelect(hwnd, directory, 4212);
  1389.  
  1390.                         strcat(directory, "*.*");
  1391.  
  1392.                         DlgDirList(hwnd, directory, 4212, 4202, 0xc010);
  1393.                         DlgDirList(hwnd, filespec, 4211, 4202, 0x0000);
  1394.  
  1395.                         SetDlgItemText(hwnd, 4201, filespec);
  1396.                         return (TRUE);
  1397.                 }
  1398.                 break;
  1399.             }
  1400.  
  1401.             case 4201:
  1402.                 if (HIWORD(lParam) == EN_CHANGE)
  1403.                     EnableWindow(GetDlgItem(hwnd, IDOK), (BOOL) SendMessage(LOWORD(lParam), WM_GETTEXTLENGTH, 0, 0L));
  1404.                 return (TRUE);
  1405.  
  1406.             case 4221:
  1407.                 if (HIWORD(lParam) == LBN_SELCHANGE) {
  1408.                     i = (WORD) SendMessage(GetDlgItem(hwnd, 4221), CB_GETCURSEL, 0, 0L);
  1409.                     strcpy(filespec,"*");
  1410.                     strcat(filespec, FileExtensions[i]);
  1411.                     SetDlgItemText(hwnd, 4201, filespec);
  1412.                     SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1413.  
  1414.                     return (TRUE);
  1415.                 }
  1416.                 break;
  1417.  
  1418.             case 4231:      /* File Find */
  1419.                 i = DialogBox(hInstance, "FileFind", hwnd, FileFindProc);
  1420.  
  1421.                 if (i) EndDialog(hwnd, TRUE);
  1422.                 return (TRUE);
  1423.  
  1424.             case IDOK:
  1425.                 GetDlgItemText(hwnd, 4201, filename, 80);
  1426.  
  1427.                 i = strlen(filename);
  1428.                 j = filename[i-1];
  1429.  
  1430.                 if (j == '\\' || j == ':') strcat(filename, "*.*");
  1431.  
  1432.                 if (strchr(filename, '*') != NULL || strchr(filename, '?') != NULL) {
  1433.                     if (DlgDirList(hwnd, filename, 4211, 4202, 0x0000)) {
  1434.                         DlgDirList(hwnd, "*.*", 4212, 4202, 0xc010);
  1435.                         strcpy(filespec, filename);
  1436.                         SetDlgItemText(hwnd, 4201, filespec);
  1437.                     } else {
  1438.                         MessageBeep(0);
  1439.                     }
  1440.  
  1441.                     return (TRUE);
  1442.                 }
  1443.  
  1444.                 strcat(strcat(filename, "\\"), "*.*");
  1445.  
  1446.                 if (DlgDirList(hwnd, filename, 4211, 4202, 0x0000)) {
  1447.                     DlgDirList(hwnd, "*.*", 4212, 4202, 0xc010);
  1448.                     strcpy(filespec, filename);
  1449.                     SetDlgItemText(hwnd, 4201, filespec);
  1450.                     return (TRUE);
  1451.                 }
  1452.  
  1453.                 filename[i] = '\0';
  1454.  
  1455.                 if (OpenFile(filename, &of, OF_READ | OF_EXIST) == -1) {
  1456.                     strcat(filename, FileExtensions[1]);    /* Normal */
  1457.                     if (OpenFile(filename, &of, OF_READ | OF_EXIST) == -1) {
  1458.                         MessageBeep(0);
  1459.                         return (TRUE);
  1460.                     }
  1461.                 }
  1462.  
  1463.                 OemToAnsi(filename, filename);
  1464.                 AnsiUpper(filename);
  1465.  
  1466.                 FormatChoice = (WORD) SendDlgItemMessage(hwnd, 4221, CB_GETCURSEL, 0, 0L);
  1467.                 ConvertLineBreaks = IsDlgButtonChecked(hwnd, 4222);
  1468.                 AlignKanjis = IsDlgButtonChecked(hwnd, 4223);
  1469.  
  1470.                 EndDialog(hwnd, TRUE);
  1471.                 return (TRUE);
  1472.  
  1473.             case IDCANCEL:
  1474.                 EndDialog(hwnd, FALSE);
  1475.                 return (TRUE);
  1476.         }
  1477.     }
  1478.  
  1479.     return (FALSE);
  1480. }
  1481.  
  1482.  
  1483.  
  1484. BOOL FAR PASCAL FileSaveAsDlgProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1485. {
  1486.     int fd;
  1487.     int i, j;
  1488.     char buffer[10];
  1489.  
  1490.  
  1491.     switch (message) {
  1492.  
  1493.     case WM_INITDIALOG:
  1494.         sprintf(filename,"*%s",FileExtensions[FF_NORMAL]);
  1495.         strcpy(filespec,filename);
  1496.  
  1497.         SendDlgItemMessage(hwnd, 4201, EM_LIMITTEXT, MAXFILENAMELEN, 0L);
  1498.         SendDlgItemMessage(hwnd, 4202, EM_LIMITTEXT, MAXFILENAMELEN, 0L);
  1499.  
  1500.         DlgDirList(hwnd, filespec, 4211, 4202, 0x0000);
  1501.         DlgDirList(hwnd, "*.*", 4212, 4202, 0xc010);
  1502.  
  1503.         SetDlgItemText(hwnd, 4201, filespec);
  1504.  
  1505.         for (i = FF_NORMAL; FileFormatNames[i] != NULL; i++)    /* Skips Auto-Detect */
  1506.             SendDlgItemMessage(hwnd, 4221, CB_INSERTSTRING, -1, (LONG) ((LPSTR) FileFormatNames[i]));
  1507.  
  1508.         /* Select the Normal format */
  1509.         SendDlgItemMessage(hwnd, 4221, CB_SETCURSEL, 0, 0L);
  1510.  
  1511.         CheckDlgButton (hwnd, 4222, 0);
  1512.         EnableWindow(GetDlgItem(hwnd, 4222), FALSE);
  1513.         SetDlgItemText(hwnd, 4223, "");
  1514.         EnableWindow(GetDlgItem(hwnd, 4223), FALSE);
  1515.  
  1516.         if (global.saveundolevels == 0) {
  1517.             CheckDlgButton (hwnd, 4224, 0);
  1518.             EnableWindow(GetDlgItem(hwnd, 4225), FALSE);
  1519.         } else {
  1520.             CheckDlgButton (hwnd, 4224, 1);
  1521.             EnableWindow(GetDlgItem(hwnd, 4225), TRUE);
  1522.         }
  1523.  
  1524.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "All");
  1525.         SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 0, 0L);
  1526.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "1");
  1527.         if (global.saveundolevels >= 1) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 1, 0L);
  1528.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "5");
  1529.         if (global.saveundolevels >= 5) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 2, 0L);
  1530.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "10");
  1531.         if (global.saveundolevels >= 10) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 3, 0L);
  1532.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "50");
  1533.         if (global.saveundolevels >= 50) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 4, 0L);
  1534.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "100");
  1535.         if (global.saveundolevels >= 100) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 5, 0L);
  1536.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "500");
  1537.         if (global.saveundolevels >= 500) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 6, 0L);
  1538.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) "1000");
  1539.         if (global.saveundolevels >= 1000) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 7, 0L);
  1540.         sprintf(buffer, "%d", MAXUNDOLEVELS);
  1541.         SendDlgItemMessage(hwnd, 4225, CB_INSERTSTRING, -1, (LONG) buffer);
  1542.         if (global.saveundolevels >= MAXUNDOLEVELS) SendDlgItemMessage(hwnd, 4225, CB_SETCURSEL, 8, 0L);
  1543.  
  1544.         CenterDialogBox(hwnd);
  1545.  
  1546.         return (TRUE);
  1547.  
  1548.     case WM_CHAR:
  1549.         switch (wParam) {
  1550.             case '\x1b': SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
  1551.                          return (TRUE);
  1552.         }
  1553.         break;
  1554.  
  1555.     case WM_COMMAND:
  1556.         switch (wParam) {
  1557.             case 4211:
  1558.                 switch (HIWORD(lParam)) {
  1559.                     case LBN_SELCHANGE:
  1560.                     case LBN_DBLCLK:
  1561.                         DlgDirSelect(hwnd, filename, 4211);
  1562.                         SetDlgItemText(hwnd, 4201, filename);
  1563.                         if (HIWORD(lParam) == LBN_DBLCLK)
  1564.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1565.                         return (TRUE);
  1566.                 }
  1567.                 break;
  1568.  
  1569.             case 4212: {
  1570.                 char directory[MAXFILENAMELEN];
  1571.  
  1572.                 switch (HIWORD(lParam)) {
  1573.                     case LBN_DBLCLK:
  1574.                         DlgDirSelect(hwnd, directory, 4212);
  1575.  
  1576.                         strcat(directory, "*.*");
  1577.  
  1578.                         DlgDirList(hwnd, directory, 4212, 4202, 0xc010);
  1579.                         DlgDirList(hwnd, filespec, 4211, 4202, 0x0000);
  1580.  
  1581.                         SetDlgItemText(hwnd, 4201, filespec);
  1582.                         return (TRUE);
  1583.                 }
  1584.                 break;
  1585.             }
  1586.  
  1587.             case 4201:
  1588.                 if (HIWORD(lParam) == EN_CHANGE)
  1589.                     EnableWindow(GetDlgItem(hwnd, IDOK), (BOOL) SendMessage(LOWORD(lParam), WM_GETTEXTLENGTH, 0, 0L));
  1590.                 return (TRUE);
  1591.  
  1592.             case 4221:
  1593.                 if (HIWORD(lParam) == LBN_SELCHANGE) {
  1594.                     i = (WORD) SendMessage(GetDlgItem(hwnd, 4221), CB_GETCURSEL, 0, 0L);
  1595.                     if (i > (FF_TEMPLATE - FF_NORMAL)) {       /* Not Normal? */
  1596.                         EnableWindow(GetDlgItem(hwnd, 4222), TRUE);
  1597.                         EnableWindow(GetDlgItem(hwnd, 4223), IsDlgButtonChecked(hwnd, 4222));
  1598.                         EnableWindow(GetDlgItem(hwnd, 4224), FALSE);
  1599.                         EnableWindow(GetDlgItem(hwnd, 4225), FALSE);
  1600.                     } else {
  1601.                         EnableWindow(GetDlgItem(hwnd, 4222), FALSE);
  1602.                         EnableWindow(GetDlgItem(hwnd, 4223), FALSE);
  1603.                         EnableWindow(GetDlgItem(hwnd, 4224), TRUE);
  1604.                         EnableWindow(GetDlgItem(hwnd, 4225), IsDlgButtonChecked(hwnd, 4224));
  1605.                     }
  1606.                     strcpy(filespec,"*");
  1607.                     strcat(filespec, FileExtensions[i + 1]);
  1608.                     SetDlgItemText(hwnd, 4201, filespec);
  1609.                     SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1610.                     return (TRUE);
  1611.                 }
  1612.                 break;
  1613.  
  1614.             case 4222:
  1615.                 if (IsDlgButtonChecked(hwnd, 4222)) {
  1616.                     sprintf(buffer, "%d", global.active->linelen);
  1617.                     EnableWindow(GetDlgItem(hwnd, 4223), TRUE);
  1618.                     SetDlgItemText(hwnd, 4223, buffer);
  1619.                 } else {
  1620.                     EnableWindow(GetDlgItem(hwnd, 4223), FALSE);
  1621.                     SetDlgItemText(hwnd, 4223, "");
  1622.                 }
  1623.                 return (TRUE);
  1624.  
  1625.             case 4224:
  1626.                 if (IsDlgButtonChecked(hwnd, 4224)) {
  1627.                     EnableWindow(GetDlgItem(hwnd, 4225), TRUE);
  1628.                 } else {
  1629.                     EnableWindow(GetDlgItem(hwnd, 4225), FALSE);
  1630.                 }
  1631.                 return (TRUE);
  1632.  
  1633.             case IDOK:
  1634.                 GetDlgItemText(hwnd, 4201, filename, 80);
  1635.  
  1636.                 i = strlen(filename);
  1637.                 j = filename[i-1];
  1638.  
  1639.                 if (j == '\\' || j == ':') strcat(filename, "*.*");
  1640.  
  1641.                 if (strchr(filename, '*') != NULL || strchr(filename, '?') != NULL) {
  1642.                     if (DlgDirList(hwnd, filename, 4211, 4202, 0x0000)) {
  1643.                         DlgDirList(hwnd, "*.*", 4212, 4202, 0xc010);
  1644.                         strcpy(filespec, filename);
  1645.                         SetDlgItemText(hwnd, 4201, filespec);
  1646.                     } else {
  1647.                         MessageBeep(0);
  1648.                     }
  1649.  
  1650.                     return (TRUE);
  1651.                 }
  1652.  
  1653.                 strcat(strcat(filename, "\\"), "*.*");
  1654.  
  1655.                 if (DlgDirList(hwnd, filename, 4211, 4202, 0x0000)) {
  1656.                     DlgDirList(hwnd, "*.*", 4212, 4202, 0xc010);
  1657.                     strcpy(filespec, filename);
  1658.                     SetDlgItemText(hwnd, 4201, filespec);
  1659.                     return (TRUE);
  1660.                 }
  1661.  
  1662.                 filename[i] = '\0';
  1663.  
  1664.                 FormatChoice = (WORD) SendDlgItemMessage(hwnd, 4221, CB_GETCURSEL, 0, 0L);
  1665.  
  1666.                 strcat(filename, FileExtensions[FormatChoice+1]);
  1667.                 AnsiUpper(filename);
  1668.  
  1669.                 if (OpenFile(filename, &of, OF_READ | OF_EXIST) != -1) {
  1670.                     switch (Confirmation (hwnd, "File %s already exists.\nOverwrite it?", filename)) {
  1671.                         case IDCANCEL: EndDialog(hwnd, FALSE); return(TRUE);
  1672.                         case IDNO:     return (TRUE);
  1673.                         case IDYES:    break;
  1674.                     }
  1675.                 } else if ((fd = OpenFile(filename, &of, OF_WRITE | OF_CREATE)) == -1) {
  1676.                     filename[i] = '\0';
  1677.                     if (OpenFile(filename, &of, OF_READ | OF_EXIST) != -1) {
  1678.                         switch (Confirmation (hwnd, "File %s already exists.\nOverwrite it?", filename)) {
  1679.                             case IDCANCEL: EndDialog(hwnd, FALSE); return(TRUE);
  1680.                             case IDNO:     return (TRUE);
  1681.                             case IDYES:    break;
  1682.                         }
  1683.                     } else if ((fd = OpenFile(filename, &of, OF_WRITE | OF_CREATE)) == -1) {
  1684.                         MessageBeep(0);
  1685.                         return (TRUE);
  1686.                     }
  1687.                 }
  1688.  
  1689.                 close(fd);
  1690.  
  1691.                 OemToAnsi(filename, filename);
  1692.  
  1693.                 OutputLineBreaks = IsDlgButtonChecked(hwnd, 4222);
  1694.                 if (OutputLineBreaks) {
  1695.                     GetDlgItemText(hwnd, 4223, buffer, 3);
  1696.                     LineLength = atoi(buffer);
  1697.                     if (LineLength <= 0) {
  1698.                         ErrorMessage(global.hwnd, "Bad Line Length: %s", buffer);
  1699.                         sprintf(buffer, "%d", global.active->linelen);
  1700.                         SetDlgItemText(hwnd, 4223, buffer);
  1701.                         return (TRUE);
  1702.                     }
  1703.                     LineLength *= 2;
  1704.                 }
  1705.  
  1706.                 if (IsDlgButtonChecked(hwnd, 4224)) {
  1707.                     i = (WORD) SendMessage(GetDlgItem(hwnd, 4225), CB_GETCURSEL, 0, 0L);
  1708.                     if (i != LB_ERR) {
  1709.                         switch (i) {
  1710.                             case 0: global.saveundolevels = -1; break;
  1711.                             case 1: global.saveundolevels = 1; break;
  1712.                             case 2: global.saveundolevels = 5; break;
  1713.                             case 3: global.saveundolevels = 10; break;
  1714.                             case 4: global.saveundolevels = 50; break;
  1715.                             case 5: global.saveundolevels = 100; break;
  1716.                             case 6: global.saveundolevels = 500; break;
  1717.                             case 7: global.saveundolevels = 1000; break;
  1718.                             case 8: global.saveundolevels = MAXUNDOLEVELS; break;
  1719.                         }
  1720.                     }
  1721.                 } else {
  1722.                     global.saveundolevels = 0;
  1723.                 }
  1724.  
  1725.  
  1726.                 EndDialog(hwnd, TRUE);
  1727.                 return (TRUE);
  1728.  
  1729.             case IDCANCEL:
  1730.                 EndDialog(hwnd, FALSE);
  1731.                 return (TRUE);
  1732.         }
  1733.     }
  1734.  
  1735.     return (FALSE);
  1736. }
  1737.