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

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5.  
  6. static PARAGRAPH far *fpara = NULL;
  7.  
  8.  
  9.  
  10. void FreeUndo (UNDOBUF far *up)
  11. {
  12.     switch (up->action) {
  13.         U_PARAFORMAT:
  14.         U_INSERT:
  15.         U_DELETE:
  16.         U_REPLACE: {
  17.             PARAGRAPH far *lp, far *lp2;
  18.  
  19.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  20.                 if (lp->text != NULL) FreeBlock(lp->text);
  21.                 lp2 = lp;
  22.                 lp = lp->next;
  23.                 FreeBlock(lp2);
  24.             }
  25.         }
  26.     }
  27.     FreeBlock(up);
  28. }
  29.  
  30.  
  31.  
  32. void FreeUndoChain (UNDOBUF far *up)
  33. {
  34.     UNDOBUF far *up1;
  35.  
  36.     for (; up != NULL; ) {
  37.         up1 = up;
  38.         up = up->next;
  39.         FreeUndo(up1);
  40.     }
  41. }
  42.  
  43.  
  44.  
  45. static int FindParaNum (FILEOPTIONS *f, PARAGRAPH far *p)
  46. {
  47.     int n;
  48.     PARAGRAPH far *p1;
  49.  
  50.     for (p1 = f->paragraph, n = 0; p1 != NULL; p1 = p1->next, n++) {
  51.         if (p1 == p) return (n);
  52.     }
  53.  
  54.     return (-1);
  55. }
  56.  
  57.  
  58.  
  59. void TrimUndoChain (FILEOPTIONS *f)
  60. {
  61.     UNDOBUF far *up;
  62.  
  63.     if (f->undo == NULL) return;
  64.  
  65.     while (f->undolevels > global.undolevels) {
  66.         if (f->undo->next == NULL) {
  67.             FreeUndo(f->undo);
  68.             f->undo = f->undotail = NULL;
  69.             f->undolevels = 0;
  70.             return;
  71.         }
  72.  
  73.         up = f->undotail->prev;
  74.         FreeUndo(f->undotail);
  75.         if (up == NULL) {
  76.             f->undo = f->undotail = NULL;
  77.             f->undolevels = 0;
  78.         } else {
  79.             up->next = NULL;
  80.             f->undotail = up;
  81.             f->undolevels--;
  82.         }
  83.     }
  84. }
  85.  
  86.  
  87.  
  88. static UNDOBUF far *CreateUndo (int para, int start, int len, UNDOACTIONS action)
  89. {
  90.     UNDOBUF far *up;
  91.  
  92.     up = StructAlloc(UNDOBUF);
  93.  
  94.     up->para1 = up->para2 = para;
  95.     up->start = start;
  96.     up->stop = start + len;
  97.     up->action = action;
  98.     up->data = NULL;
  99.     up->next = up->prev = NULL;
  100.  
  101.     return (up);
  102. }
  103.  
  104.  
  105.  
  106. void UndoAddTyping (FILEOPTIONS *f, POSITION p, int howmany, BOOL splitline)
  107. {
  108.     int para, start;
  109.     UNDOBUF far *up;
  110.     time_t tm;
  111.  
  112.  
  113.     if (global.undolevels == 0) return;
  114.     if (!(f->type & FN_NORMAL)) return;
  115.  
  116.     FreeUndoChain(f->redo);
  117.     f->redo = NULL;
  118.  
  119.     para = FindParaNum(f, PARAOF(p));
  120.     start = POS2ABS(p);
  121.  
  122.     up = f->undo;
  123.  
  124.     if (splitline) {
  125.         if (up == NULL) {
  126.             up = f->undo = f->undotail = CreateUndo(para, start, 0, U_INSERT);
  127.             up->para2 = para + 1;
  128.             up->stop = 0;
  129.             f->undolevels = 1;
  130.         } else if ((up->action == U_INSERT || up->action == U_REPLACE) &&
  131.                    up->para2 == para && up->stop == start) {
  132.             up->para2 = para + 1;
  133.             up->stop = 0;
  134.         } else {
  135.             up = CreateUndo(para, start, 0, U_INSERT);
  136.             up->para2 = para + 1;
  137.             up->stop = 0;
  138.             up->next = f->undo;
  139.             f->undo->prev = up;
  140.             f->undo = up;
  141.             f->undolevels++;
  142.             TrimUndoChain(f);
  143.         }
  144.     } else {
  145.         if (up == NULL) {
  146.             up = f->undo = f->undotail = CreateUndo(para, start, howmany, U_INSERT);
  147.             f->undolevels = 1;
  148.         } else if ((up->action != U_INSERT && up->action != U_REPLACE) ||
  149.                    up->para2 != para || up->stop != start) {
  150.  
  151.             up = CreateUndo(para, start, howmany, U_INSERT);
  152.             up->next = f->undo;
  153.             f->undo->prev = up;
  154.             f->undo = up;
  155.             f->undolevels++;
  156.             TrimUndoChain(f);
  157.         } else {
  158.             up->stop += howmany;
  159.         }
  160.     }
  161.  
  162.     time(&tm);
  163.     up->time = tm;
  164. }
  165.  
  166.  
  167.  
  168. void UndoFixConvert (FILEOPTIONS *f, POSITION p, int oldlen, int newlen)
  169. {
  170.     UNDOBUF far *up;
  171.     time_t tm;
  172.  
  173.     if (global.undolevels == 0) return;
  174.     if (f->undo == NULL) return;
  175.     if (!(f->type & FN_NORMAL)) return;
  176.  
  177.     up = f->undo;
  178.     if (up->action != U_INSERT && up->action != U_REPLACE) return;
  179.     if (up->para2 != FindParaNum(f, PARAOF(p))) return;
  180.     //if (up->stop != POS2ABS(p) + oldlen) return;
  181.     if (up->stop <= POS2ABS(p)) return;
  182.  
  183.     up->stop += newlen - oldlen;
  184.  
  185.     time(&tm);
  186.     up->time = tm;
  187. }
  188.  
  189.  
  190.  
  191. void UndoAddInsert (FILEOPTIONS *f, POSITION p1, POSITION p2)
  192. {
  193.     UNDOBUF far *up;
  194.     int para1, para2;
  195.     time_t tm;
  196.  
  197.     if (global.undolevels == 0) return;
  198.     if (!(f->type & FN_NORMAL)) return;
  199.  
  200.     FreeUndoChain(f->redo);
  201.     f->redo = NULL;
  202.  
  203.     para1 = FindParaNum(f, PARAOF(p1));
  204.     para2 = FindParaNum(f, PARAOF(p2));
  205.  
  206.     if (f->undo == NULL) {
  207.         up = f->undo = f->undotail = CreateUndo(para1, POS2ABS(p1), 0, U_INSERT);
  208.         up->para2 = para2;
  209.         up->stop = POS2ABS(p2);
  210.         f->undolevels = 1;
  211.     } else {
  212.         up = CreateUndo(para1, POS2ABS(p1), 0, U_INSERT);
  213.         up->para2 = para2;
  214.         up->stop = POS2ABS(p2);
  215.         up->next = f->undo;
  216.         f->undo->prev = up;
  217.         f->undo = up;
  218.         f->undolevels++;
  219.         TrimUndoChain(f);
  220.     }
  221.  
  222.     time(&tm);
  223.     up->time = tm;
  224. }
  225.  
  226.  
  227.  
  228. static PARAGRAPH far *SaveData (FILEOPTIONS *f, POSITION p1, POSITION p2)
  229. {
  230.     unsigned int len;
  231.     PARAGRAPH far *data = NULL, far *p, far *lp;
  232.  
  233.     if (PARAOF(p1) == PARAOF(p2)) {
  234.         lp = StructAlloc(PARAGRAPH);
  235.         _fmemcpy(lp, PARAOF(p1), sizeof(PARAGRAPH));
  236.  
  237.         lp->lines = lp->lastline = NULL;
  238.         lp->next = lp->prev = NULL;
  239.         len = POSOF(p2) - POSOF(p1);
  240.  
  241.         lp->textsize = (len + 2) * sizeof(UNIT);
  242.         lp->text = BlockAlloc(lp->textsize);
  243.  
  244.         _fmemcpy(lp->text, PARAOF(p1)->text + POSOF(p1), len * sizeof(UNIT));
  245.         lp->text[len].kanji = 0;
  246.  
  247.         return (lp);
  248.     }
  249.  
  250.     for (p = PARAOF(p1); ; p = p->next) {
  251.         if (data == NULL) {
  252.             data = lp = StructAlloc(PARAGRAPH);
  253.             _fmemcpy(lp, p, sizeof(PARAGRAPH));
  254.             lp->prev = NULL;
  255.         } else {
  256.             lp->next = StructAlloc(PARAGRAPH);
  257.             _fmemcpy(lp->next, p, sizeof(PARAGRAPH));
  258.             lp->next->prev = lp;
  259.             lp = lp->next;
  260.         }
  261.  
  262.         lp->next = NULL;
  263.         lp->lines = lp->lastline = NULL;
  264.  
  265.         if (p == PARAOF(p1)) {
  266.             len = unitlen(p->text) - POSOF(p1);
  267.             lp->textsize = (len + 2) * sizeof(UNIT);
  268.             lp->text = BlockAlloc(lp->textsize);
  269.             _fmemcpy(lp->text, p->text + POSOF(p1), len * sizeof(UNIT));
  270.             lp->text[len].kanji = 0;
  271.         } else if (p == PARAOF(p2)) {
  272.             len = POSOF(p2);
  273.             lp->textsize = (len + 2) * sizeof(UNIT);
  274.             lp->text = BlockAlloc(lp->textsize);
  275.             _fmemcpy(lp->text, p->text, len * sizeof(UNIT));
  276.             lp->text[len].kanji = 0;
  277.             break;
  278.         } else {
  279.             len = unitlen(p->text);
  280.             lp->textsize = (len + 2) * sizeof(UNIT);
  281.             lp->text = BlockAlloc(lp->textsize);
  282.             _fmemcpy(lp->text, p->text, len * sizeof(UNIT));
  283.             lp->text[len].kanji = 0;
  284.         }
  285.     }
  286.  
  287.     return (data);
  288. }
  289.  
  290.  
  291.  
  292. void UndoAddDelete (FILEOPTIONS *f, POSITION p1, POSITION p2)
  293. {
  294.     UNDOBUF far *up;
  295.     int para1, para2;
  296.     time_t tm;
  297.  
  298.     if (global.undolevels == 0) return;
  299.     if (!(f->type & FN_NORMAL)) return;
  300.  
  301.     FreeUndoChain(f->redo);
  302.     f->redo = NULL;
  303.  
  304.     para1 = FindParaNum(f, PARAOF(p1));
  305.     POSOF(p1) = POS2ABS(p1);
  306.     para2 = FindParaNum(f, PARAOF(p2));
  307.     POSOF(p2) = POS2ABS(p2);
  308.  
  309.     if (f->undo == NULL) {
  310.         up = f->undo = f->undotail = CreateUndo(para1, POSOF(p1), 0, U_DELETE);
  311.         up->para2 = para2;
  312.         up->stop = POSOF(p2);
  313.         f->undolevels = 1;
  314.     } else {
  315.         up = CreateUndo(para1, POSOF(p1), 0, U_DELETE);
  316.         up->para2 = para2;
  317.         up->stop = POSOF(p2);
  318.         up->next = f->undo;
  319.         f->undo->prev = up;
  320.         f->undo = up;
  321.         f->undolevels++;
  322.         TrimUndoChain(f);
  323.     }
  324.  
  325.     up->data = SaveData(f, p1, p2);
  326.  
  327.     time(&tm);
  328.     up->time = tm;
  329. }
  330.  
  331.  
  332.  
  333. void UndoJoinLine (FILEOPTIONS *f, POSITION p)
  334. {
  335.     int para, start;
  336.     UNDOBUF far *up;
  337.     PARAGRAPH far *pp;
  338.     time_t tm;
  339.  
  340.  
  341.     if (global.undolevels == 0) return;
  342.     if (!(f->type & FN_NORMAL)) return;
  343.  
  344.  
  345.     para = FindParaNum(f, PARAOF(p));
  346.     start = POS2ABS(p);
  347.  
  348.     up = f->undo;
  349.  
  350.     if (up == NULL) {
  351.         up = f->undo = f->undotail = CreateUndo(para, start, 0, U_DELETE);
  352.         up->para2 = para + 1;
  353.         up->stop = 0;
  354.         f->undolevels = 1;
  355.  
  356.         pp = StructAlloc(PARAGRAPH);
  357.         up->data = (void far *) pp;
  358.  
  359.         _fmemcpy(pp, PARAOF(p), sizeof(PARAGRAPH));
  360.         pp->lines = pp->lastline = NULL;
  361.         pp->prev = NULL;
  362.         pp->text = NULL;
  363.         pp->next = StructAlloc(PARAGRAPH);
  364.         _fmemcpy(pp->next, PARAOF(p)->next, sizeof(PARAGRAPH));
  365.         pp->next->prev = pp;
  366.         pp = pp->next;
  367.         pp->next = NULL;
  368.         pp->text = NULL;
  369.     } else if (up->action == U_DELETE && up->para1 == para &&
  370.                up->start == start) {
  371.         up->para2 = para + 1;
  372.         up->stop = 0;
  373.  
  374.         for (pp = (PARAGRAPH far *) up->data; pp->next != NULL; pp = pp->next);
  375.  
  376.         pp->next = StructAlloc(PARAGRAPH);
  377.         _fmemcpy(pp->next, PARAOF(p)->next, sizeof(PARAGRAPH));
  378.         pp->next->prev = pp;
  379.         pp = pp->next;
  380.         pp->next = NULL;
  381.         pp->text = NULL;
  382.     } else if (up->action == U_DELETE && up->para1 == para + 1 &&
  383.                up->start == 0) {
  384.         up->para1 = para;
  385.         up->start = start;
  386.  
  387.         pp = (PARAGRAPH far *) up->data;
  388.         pp->prev = StructAlloc(PARAGRAPH);
  389.         _fmemcpy(pp->prev, PARAOF(p), sizeof(PARAGRAPH));
  390.         pp->prev->next = pp;
  391.         pp = pp->prev;
  392.         pp->prev = NULL;
  393.         pp->text = NULL;
  394.  
  395.         up->data = (void far *) pp;
  396.     } else {
  397.         up = CreateUndo(para, start, 0, U_DELETE);
  398.         up->para2 = para + 1;
  399.         up->stop = 0;
  400.         up->next = f->undo;
  401.         f->undo->prev = up;
  402.         f->undo = up;
  403.         f->undolevels++;
  404.         TrimUndoChain(f);
  405.  
  406.         pp = StructAlloc(PARAGRAPH);
  407.         up->data = (void far *) pp;
  408.  
  409.         _fmemcpy(pp, PARAOF(p), sizeof(PARAGRAPH));
  410.         pp->lines = pp->lastline = NULL;
  411.         pp->prev = NULL;
  412.         pp->text = NULL;
  413.         pp->next = StructAlloc(PARAGRAPH);
  414.         _fmemcpy(pp->next, PARAOF(p)->next, sizeof(PARAGRAPH));
  415.         pp->next->prev = pp;
  416.         pp = pp->next;
  417.         pp->next = NULL;
  418.         pp->text = NULL;
  419.     }
  420.  
  421.     time(&tm);
  422.     up->time = tm;
  423. }
  424.  
  425.  
  426.  
  427. void UndoAddErase (FILEOPTIONS *f, POSITION p, int howmany)
  428. {
  429.     int para, start;
  430.     unsigned int i, n, len;
  431.     UNDOBUF far *up;
  432.     POSITION p1, p2;
  433.     PARAGRAPH far *pp;
  434.     time_t tm;
  435.  
  436.  
  437.     if (global.undolevels == 0) return;
  438.     if (!(f->type & FN_NORMAL)) return;
  439.  
  440.     FreeUndoChain(f->redo);
  441.     f->redo = NULL;
  442.  
  443.     para = FindParaNum(f, PARAOF(p));
  444.     start = POS2ABS(p);
  445.     p1 = p;
  446.     POSOF(p1) = start;
  447.     p2 = p1;
  448.     POSOF(p2) += howmany;
  449.  
  450.     up = f->undo;
  451.  
  452.     if (up == NULL) {
  453.         up = f->undo = f->undotail = CreateUndo(para, start, howmany, U_DELETE);
  454.         up->data = SaveData(f, p1, p2);
  455.         f->undolevels = 1;
  456.     } else if (up->action == U_DELETE && up->para1 == para && up->start == start) {
  457.         up->stop += howmany;
  458.  
  459.         for (pp = (PARAGRAPH far *) up->data; pp->next != NULL; pp = pp->next);
  460.  
  461.         if (pp->text == NULL) {
  462.             n = (howmany + 2) / UNDOTEXTSIZE;
  463.             n = (n + 1 ) * UNDOTEXTSIZE;
  464.             pp->text = (UNIT far *) BlockAlloc(n * sizeof(UNIT));
  465.             len = 0;
  466.         } else {
  467.             n = SegHeapGetSize(pp->text) / sizeof(UNIT);
  468.             len = unitlen(pp->text);
  469.             if (len + howmany + 2 > n) {
  470.                 n = (len + howmany + 2) / UNDOTEXTSIZE;
  471.                 n = (n + 1 ) * UNDOTEXTSIZE;
  472.  
  473.                 pp->text = (UNIT far *) SegHeapRealloc(pp->text, n * sizeof(UNIT));
  474.             }
  475.         }
  476.  
  477.         for (i = 0; i < howmany; i++) {
  478.             pp->text[len + i] = PARAOF(p)->text[start + i];
  479.         }
  480.         pp->text[len + i].kanji = 0;
  481.     } else if (up->action == U_DELETE && up->para1 == para && up->start == start + howmany) {
  482.         up->start = start;
  483.  
  484.         pp = (PARAGRAPH far *) up->data;
  485.  
  486.         if (pp->text == NULL) {
  487.             n = (howmany + 2) / UNDOTEXTSIZE;
  488.             n = (n + 1 ) * UNDOTEXTSIZE;
  489.             pp->text = (UNIT far *) BlockAlloc(n * sizeof(UNIT));
  490.             len = 0;
  491.         } else {
  492.             n = SegHeapGetSize(pp->text) / sizeof(UNIT);
  493.             len = unitlen(pp->text);
  494.             if (len + howmany + 2 > n) {
  495.                 n = (len + howmany + 2) / UNDOTEXTSIZE;
  496.                 n = (n + 1 ) * UNDOTEXTSIZE;
  497.  
  498.                 pp->text = (UNIT far *) SegHeapRealloc(pp->text, n * sizeof(UNIT));
  499.             }
  500.         }
  501.  
  502.         if (len >= 1) {
  503.             for (i = len - 1; i >= 0; i--) {
  504.                 pp->text[i + howmany] = pp->text[i];
  505.                 if (i == 0) break;
  506.             }
  507.         }
  508.         pp->text[len + howmany].kanji = 0;
  509.  
  510.         for (i = 0; i < howmany; i++) {
  511.             pp->text[i] = PARAOF(p)->text[start + i];
  512.         }
  513.     } else {
  514.         up = CreateUndo(para, start, howmany, U_DELETE);
  515.         up->data = SaveData(f, p1, p2);
  516.         up->next = f->undo;
  517.         f->undo->prev = up;
  518.         f->undo = up;
  519.         f->undolevels++;
  520.         TrimUndoChain(f);
  521.     }
  522.  
  523.     time(&tm);
  524.     up->time = tm;
  525. }
  526.  
  527.  
  528.  
  529. void UndoAddReplace (FILEOPTIONS *f, POSITION p1, POSITION p2)
  530. {
  531.     UNDOBUF far *up;
  532.     int para1;
  533.     time_t tm;
  534.  
  535.     if (global.undolevels == 0) return;
  536.     if (!(f->type & FN_NORMAL)) return;
  537.  
  538.     FreeUndoChain(f->redo);
  539.     f->redo = NULL;
  540.  
  541.     para1 = FindParaNum(f, PARAOF(p1));
  542.     POSOF(p1) = POS2ABS(p1);
  543.     POSOF(p2) = POS2ABS(p2);
  544.  
  545.     if (f->undo == NULL) {
  546.         up = f->undo = f->undotail = CreateUndo(para1, POSOF(p1), 0, U_REPLACE);
  547.         f->undolevels = 1;
  548.     } else {
  549.         up = CreateUndo(para1, POSOF(p1), 0, U_REPLACE);
  550.         up->next = f->undo;
  551.         f->undo->prev = up;
  552.         f->undo = up;
  553.         f->undolevels++;
  554.         TrimUndoChain(f);
  555.     }
  556.  
  557.     up->data = SaveData(f, p1, p2);
  558.  
  559.     time(&tm);
  560.     up->time = tm;
  561. }
  562.  
  563.  
  564.  
  565. void UndoFixReplace (FILEOPTIONS *f, POSITION p)
  566. {
  567.     if (!(f->type & FN_NORMAL)) return;
  568.     if (f->undo == NULL) return;
  569.     if (f->undo->action != U_REPLACE) return;
  570.  
  571.     f->undo->para2 = FindParaNum(f, PARAOF(p));
  572.     f->undo->stop = POS2ABS(p);
  573. }
  574.  
  575.  
  576.  
  577. static PARAGRAPH far *SaveFormatting (FILEOPTIONS *f, POSITION p1, POSITION p2)
  578. {
  579.     PARAGRAPH far *pp, far *savepp = NULL, far *pp1;
  580.  
  581.     for (pp = PARAOF(p1); ; pp = pp->next) {
  582.         if (savepp == NULL) {
  583.             pp1 = savepp = StructAlloc(PARAGRAPH);
  584.             _fmemcpy(savepp, pp, sizeof(PARAGRAPH));
  585.             savepp->next = savepp->prev = NULL;
  586.         } else {
  587.             pp1->next = StructAlloc(PARAGRAPH);
  588.             _fmemcpy(pp1->next, pp, sizeof(PARAGRAPH));
  589.             pp1->next->prev = pp1;
  590.             pp1 = pp1->next;
  591.             pp1->next = NULL;
  592.         }
  593.  
  594.         pp1->text = NULL;
  595.         if (pp == PARAOF(p2)) break;
  596.     }
  597.  
  598.     return (savepp);
  599. }
  600.  
  601.  
  602.  
  603. void UndoAddFormatParagraph (FILEOPTIONS *f, POSITION p1, POSITION p2)
  604. {
  605.     int para;
  606.     UNDOBUF far *up;
  607.     PARAGRAPH far *savepp;
  608.     time_t tm;
  609.  
  610.  
  611.     if (global.undolevels == 0) return;
  612.     if (!(f->type & FN_NORMAL)) return;
  613.  
  614.     FreeUndoChain(f->redo);
  615.     f->redo = NULL;
  616.  
  617.     savepp = SaveFormatting(f, p1, p2);
  618.  
  619.     para = FindParaNum(f, PARAOF(p1));
  620.     up = f->undo;
  621.  
  622.     if (up == NULL) {
  623.         up = f->undo = f->undotail = CreateUndo(para, 0, 0, U_PARAFORMAT);
  624.         up->para2 = FindParaNum(f, PARAOF(p2));
  625.         up->data = (void far *) savepp;
  626.         f->undolevels = 1;
  627.     } else {
  628.         up = CreateUndo(para, 0, 0, U_PARAFORMAT);
  629.         up->para2 = FindParaNum(f, PARAOF(p2));
  630.         up->data = (void far *) savepp;
  631.         up->next = f->undo;
  632.         f->undo->prev = up;
  633.         f->undo = up;
  634.         f->undolevels++;
  635.         TrimUndoChain(f);
  636.     }
  637.  
  638.     time(&tm);
  639.     up->time = tm;
  640. }
  641.  
  642.  
  643.  
  644. static PARAGRAPH far *FindParaFromNum (FILEOPTIONS *f, int num)
  645. {
  646.     int i;
  647.     PARAGRAPH far *p;
  648.  
  649.     for (i = 0, p = f->paragraph; i < num && p != NULL; i++, p = p->next);
  650.  
  651.     return (p);
  652. }
  653.  
  654.  
  655.  
  656. static void MoveToPosition (FILEOPTIONS *f, POSITION p)
  657. {
  658.     f->current = p;
  659.  
  660.     //if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
  661.  
  662.     if (!FindCaret(f, TRUE)) {
  663.         MoveIntoWindow(f);
  664.         InvalidateRect(f->hwnd, NULL, TRUE);
  665.         UpdateWindow(f->hwnd);
  666.     } else {
  667.         TurnOffSelection(f);
  668.     }
  669.  
  670.     //f->pseudo = f->cursor;
  671.     //DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
  672.     //Triangles(f);
  673. }
  674.  
  675.  
  676.  
  677. static BOOL ReformatProc (FILEOPTIONS *f, PARAGRAPH far *p, int n)
  678. {
  679.     int i;
  680.     PARAGRAPH far *lp;
  681.  
  682.     /* Find the paragraph */
  683.  
  684.     for (i = 0, lp = fpara; i < n && lp != NULL; i++, lp = lp->next);
  685.  
  686.     if (lp == NULL) return (FALSE);
  687.  
  688.     p->spacemulti = lp->spacemulti;
  689.     p->spacing = (f->basefont->height + f->basefont->spacing) * p->spacemulti / 100;
  690.     p->spacing -= f->basefont->height;
  691.  
  692.     p->firstindent = lp->firstindent;
  693.     p->leftindent = lp->leftindent;
  694.     p->rightindent = lp->rightindent;
  695.  
  696.     return (TRUE);
  697. }
  698.  
  699.  
  700. static PARAGRAPH far *PackData (PARAGRAPH far *lp, KANJI far *buf, unsigned int size)
  701. {
  702.     unsigned int i, j, k;
  703.  
  704.     for (i = 0; lp != NULL; lp = lp->next) {
  705.         if (lp->text != NULL) {
  706.             j = unitlen(lp->text);
  707.  
  708.             if (i + j > size + 5) break;
  709.  
  710.             for (k = 0; k < j; k++) buf[i++] = lp->text[k].kanji;
  711.         }
  712.         buf[i++] = '\r';
  713.     }
  714.  
  715.     if (i > 0) buf[--i] = 0;       /* Get rid of last CR */
  716.     else buf[i] = 0;
  717.  
  718.     return (lp);
  719. }
  720.  
  721.  
  722.  
  723. void UndoOneStep (FILEOPTIONS *f)
  724. {
  725.     int i, j;
  726.     UNDOBUF far *up;
  727.     POSITION p, p1, p2;
  728.     PARAGRAPH far *lp;
  729.     HCURSOR hcursor;
  730.     KANJI buf[MAXLINELEN];
  731.  
  732.     if (f->undo == NULL) return;
  733.  
  734.     PARAOF(p) = FindParaFromNum(f, f->undo->para1);
  735.     if (PARAOF(p) == NULL) return;
  736.  
  737.     POSOF(p) = f->undo->start;
  738.  
  739.     hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  740.     ShowCursor(TRUE);
  741.  
  742.     up = f->undo;
  743.  
  744.     switch (up->action) {
  745.         case U_INSERT:
  746.             PARAOF(p2) = FindParaFromNum(f, up->para2);
  747.             POSOF(p2) = up->stop;
  748.             up->data = SaveData(f, p, p2);
  749.  
  750.             AbsoluteToPosition(p, &p1);
  751.             PARAOF(p) = FindParaFromNum(f, up->para2);
  752.             POSOF(p) = up->stop - 1;
  753.             AbsoluteToPosition(p, &p2);
  754.  
  755.             MoveToPosition(f, p1);
  756.  
  757.             BlockDelete (f, p1, p2);
  758.             break;
  759.  
  760.         case U_DELETE: {
  761.             unsigned int blocksize;
  762.             KANJI far *kp;
  763.             PARAGRAPH far *lp, far *lp2;
  764.  
  765.             AbsoluteToPosition(p, &p1);
  766.             MoveToPosition(f, p1);
  767.  
  768.             SetReformatProc(ReformatProc);
  769.             blocksize = C64K/sizeof(KANJI);
  770.             kp = (KANJI far *) BlockAlloc (C64K);
  771.  
  772.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  773.                 fpara = lp;
  774.                 lp = PackData(lp, kp, blocksize);
  775.                 InsertString(f, f->current, kp, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  776.             }
  777.  
  778.             FreeBlock(kp);
  779.             SetReformatProc(NULL);
  780.  
  781.             /* Free the data */
  782.  
  783.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  784.                 if (lp->text != NULL) FreeBlock(lp->text);
  785.                 lp2 = lp;
  786.                 lp = lp->next;
  787.                 FreeBlock(lp2);
  788.             }
  789.             up->data = NULL;
  790.             break;
  791.         }
  792.  
  793.         case U_REPLACE: {
  794.             unsigned int blocksize;
  795.             KANJI far *kp;
  796.             BOOL replace = TRUE;
  797.             PARAGRAPH far *lp, far *lp2, far *savepp;
  798.  
  799.             PARAOF(p2) = FindParaFromNum(f, up->para2);
  800.             POSOF(p2) = up->stop;
  801.             savepp = SaveData(f, p, p2);
  802.  
  803.             AbsoluteToPosition(p, &p1);
  804.             PARAOF(p) = FindParaFromNum(f, up->para2);
  805.             POSOF(p) = up->stop - 1;
  806.             AbsoluteToPosition(p, &p2);
  807.  
  808.             MoveToPosition(f, p1);
  809.  
  810.             SetReformatProc(ReformatProc);
  811.             blocksize = C64K/sizeof(KANJI);
  812.             kp = (KANJI far *) BlockAlloc (C64K);
  813.  
  814.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  815.                 fpara = lp;
  816.                 lp = PackData(lp, kp, blocksize);
  817.                 if (replace) {
  818.                     f->current = p2;
  819.                     CURCHAR(f)++;
  820.                     BlockReplace(f, p1, p2, kp);
  821.                     replace = FALSE;
  822.                 } else {
  823.                     InsertString(f, f->current, kp, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  824.                 }
  825.             }
  826.  
  827.             FreeBlock(kp);
  828.             SetReformatProc(NULL);
  829.  
  830.             up->para2 = FindParaNum(f, CURPARA(f));
  831.             up->stop = POS2ABS(f->current);
  832.  
  833.             /* Free the data */
  834.  
  835.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  836.                 if (lp->text != NULL) FreeBlock(lp->text);
  837.                 lp2 = lp;
  838.                 lp = lp->next;
  839.                 FreeBlock(lp2);
  840.             }
  841.  
  842.             up->data = savepp;
  843.             break;
  844.         }
  845.  
  846.         case U_PARAFORMAT: {
  847.             PARAGRAPH far *lp, far *lp2, far *savepp;
  848.  
  849.             LINEOF(p) = PARAOF(p)->lines;
  850.             POSOF(p) = 0;
  851.  
  852.             PARAOF(p2) = FindParaFromNum(f, up->para2);
  853.  
  854.             MoveToPosition(f, p);
  855.  
  856.             /* Save the formatting */
  857.  
  858.             savepp = SaveFormatting(f, p, p2);
  859.  
  860.             fpara = (PARAGRAPH far *) up->data;
  861.             SetReformatProc(ReformatProc);
  862.             ReformatParagraph(f, p, PARAOF(p2)->next, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  863.             SetReformatProc(NULL);
  864.  
  865.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  866.                 if (lp->text != NULL) FreeBlock(lp->text);
  867.                 lp2 = lp;
  868.                 lp = lp->next;
  869.                 FreeBlock(lp2);
  870.             }
  871.  
  872.             up->data = savepp;
  873.             break;
  874.         }
  875.     }
  876.  
  877.     ShowCursor(FALSE);
  878.     SetCursor(hcursor);
  879.  
  880.     f->undo = up->next;
  881.     if (up == NULL) {
  882.         f->undotail = NULL;
  883.         f->undolevels = 0;
  884.     } else {
  885.         f->undolevels--;
  886.     }
  887.  
  888.     // FreeUndo(up);
  889.  
  890.     up->next = f->redo;
  891.     if (f->redo != NULL) f->redo->prev = up;
  892.     f->redo = up;
  893. }
  894.  
  895.  
  896.  
  897. void RedoOneStep (FILEOPTIONS *f)
  898. {
  899.     int i, j;
  900.     UNDOBUF far *up;
  901.     POSITION p, p1, p2;
  902.     PARAGRAPH far *lp;
  903.     HCURSOR hcursor;
  904.     KANJI buf[MAXLINELEN];
  905.  
  906.     if (f->redo == NULL) return;
  907.  
  908.     PARAOF(p) = FindParaFromNum(f, f->redo->para1);
  909.     if (PARAOF(p) == NULL) return;
  910.  
  911.     POSOF(p) = f->redo->start;
  912.  
  913.     hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  914.     ShowCursor(TRUE);
  915.  
  916.     up = f->redo;
  917.  
  918.     switch (up->action) {
  919.         case U_DELETE:
  920.             PARAOF(p2) = FindParaFromNum(f, up->para2);
  921.             POSOF(p2) = up->stop;
  922.             up->data = SaveData(f, p, p2);
  923.  
  924.             AbsoluteToPosition(p, &p1);
  925.             PARAOF(p) = FindParaFromNum(f, up->para2);
  926.             POSOF(p) = up->stop - 1;
  927.             AbsoluteToPosition(p, &p2);
  928.  
  929.             MoveToPosition(f, p1);
  930.  
  931.             BlockDelete (f, p1, p2);
  932.             break;
  933.  
  934.         case U_INSERT: {
  935.             unsigned int blocksize;
  936.             KANJI far *kp;
  937.             PARAGRAPH far *lp, far *lp2;
  938.  
  939.             AbsoluteToPosition(p, &p1);
  940.             MoveToPosition(f, p1);
  941.  
  942.             SetReformatProc(ReformatProc);
  943.             blocksize = C64K/sizeof(KANJI);
  944.             kp = (KANJI far *) BlockAlloc (C64K);
  945.  
  946.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  947.                 fpara = lp;
  948.                 lp = PackData(lp, kp, blocksize);
  949.                 InsertString(f, f->current, kp, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  950.             }
  951.  
  952.             FreeBlock(kp);
  953.             SetReformatProc(NULL);
  954.  
  955.             /* Free the data */
  956.  
  957.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  958.                 if (lp->text != NULL) FreeBlock(lp->text);
  959.                 lp2 = lp;
  960.                 lp = lp->next;
  961.                 FreeBlock(lp2);
  962.             }
  963.             up->data = NULL;
  964.             break;
  965.         }
  966.  
  967.         case U_REPLACE: {
  968.             unsigned int blocksize;
  969.             KANJI far *kp;
  970.             BOOL replace = TRUE;
  971.             PARAGRAPH far *lp, far *lp2, far *savepp;
  972.  
  973.             PARAOF(p2) = FindParaFromNum(f, up->para2);
  974.             POSOF(p2) = up->stop;
  975.             savepp = SaveData(f, p, p2);
  976.  
  977.             AbsoluteToPosition(p, &p1);
  978.             PARAOF(p) = FindParaFromNum(f, up->para2);
  979.             POSOF(p) = up->stop - 1;
  980.             AbsoluteToPosition(p, &p2);
  981.  
  982.             MoveToPosition(f, p1);
  983.  
  984.             SetReformatProc(ReformatProc);
  985.             blocksize = C64K/sizeof(KANJI);
  986.             kp = (KANJI far *) BlockAlloc (C64K);
  987.  
  988.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  989.                 fpara = lp;
  990.                 lp = PackData(lp, kp, blocksize);
  991.                 if (replace) {
  992.                     f->current = p2;
  993.                     CURCHAR(f)++;
  994.                     BlockReplace(f, p1, p2, kp);
  995.                     replace = FALSE;
  996.                 } else {
  997.                     InsertString(f, f->current, kp, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  998.                 }
  999.             }
  1000.  
  1001.             FreeBlock(kp);
  1002.             SetReformatProc(NULL);
  1003.  
  1004.             up->para2 = FindParaNum(f, CURPARA(f));
  1005.             up->stop = POS2ABS(f->current);
  1006.  
  1007.             /* Free the data */
  1008.  
  1009.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  1010.                 if (lp->text != NULL) FreeBlock(lp->text);
  1011.                 lp2 = lp;
  1012.                 lp = lp->next;
  1013.                 FreeBlock(lp2);
  1014.             }
  1015.  
  1016.             up->data = savepp;
  1017.             break;
  1018.         }
  1019.  
  1020.         case U_PARAFORMAT: {
  1021.             PARAGRAPH far *lp, far *lp2, far *savepp;
  1022.  
  1023.             LINEOF(p) = PARAOF(p)->lines;
  1024.             POSOF(p) = 0;
  1025.  
  1026.             PARAOF(p2) = FindParaFromNum(f, up->para2);
  1027.  
  1028.             MoveToPosition(f, p);
  1029.  
  1030.             /* Save the formatting */
  1031.  
  1032.             savepp = SaveFormatting(f, p, p2);
  1033.  
  1034.             fpara = (PARAGRAPH far *) up->data;
  1035.             SetReformatProc(ReformatProc);
  1036.             ReformatParagraph(f, p, PARAOF(p2)->next, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  1037.             SetReformatProc(NULL);
  1038.  
  1039.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  1040.                 if (lp->text != NULL) FreeBlock(lp->text);
  1041.                 lp2 = lp;
  1042.                 lp = lp->next;
  1043.                 FreeBlock(lp2);
  1044.             }
  1045.  
  1046.             up->data = savepp;
  1047.             break;
  1048.         }
  1049.     }
  1050.  
  1051.     ShowCursor(FALSE);
  1052.     SetCursor(hcursor);
  1053.  
  1054.     f->redo = up->next;
  1055.  
  1056.     up->next = f->undo;
  1057.     if (f->undo == NULL) {
  1058.         f->undotail = up;
  1059.         f->undolevels = 1;
  1060.     } else {
  1061.         f->undo->prev = up;
  1062.         f->undolevels++;
  1063.     }
  1064.     f->undo = up;
  1065. }
  1066.