home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 361_01 / gadgets.txt < prev    next >
Text File  |  1991-09-20  |  50KB  |  1,558 lines

  1.  
  2.  
  3. /* Gadgetx.lib ---> A Custom Turbo-C Library "Bag of Tricks".
  4.  *
  5.  * J.Ekwall                        30 August 91
  6.  *
  7.  * Copyrighted to the Public Domain.  Unlimited    Distribution Authorized.
  8.  *
  9.  * User    Assumes    All Risks/Liabilities.
  10.  *
  11.  * Last    Update:    16 September 91/EK
  12.  */
  13.  
  14. ============================================================================
  15.  
  16.    The need for    "Gadgets" to extend the    reach of ANSI-C    has spun off many 
  17. commercially available "External" Libraries, among these C-Express and 
  18. Vitamin-C.  The    need to    freely distribute Tools    limits their usefulness, 
  19. particularly in    our current User-Hostile ADPE environment.
  20.  
  21.    These routines are Public Domain, either home-grown,    taken from other 
  22. Public Domain sources (such as C User's    Croup (CUG)), taken from Publications
  23. or lifted from Shareware and significantly modified/enhanced (nullifying 
  24. the original copyright).  CUG sources are identified by    their distribution 
  25. disk number, ie. [CUG-273] is "TurboC Utilities" developed By Jim Derr,
  26. 2425 Santa Cruz    Ct., Santa Rosa, Ca. 95401.
  27.  
  28. ========================================================================
  29.  
  30. Notes:
  31.     1. On the CRT, X ranges 1-80, Y ranges 1-25.
  32.     2. Direct Video Routines use Vpeek/Vpoke which are hardwired for
  33.        Color CGA/EGA/VGA Video RAM based at 0xB800.
  34.  
  35. -------------------------------------------------------------------------
  36.  
  37. >AnyCharacter.  Pop a Query Window for an Ascii    Value.
  38.  
  39. int AnyCharacter(void)
  40. { /* Create Any    Character */
  41.     int    c, ch =    0, n = 3, xx, yy;
  42.     char FootPrint[216];
  43.  
  44.  /* Ask    'em */
  45.     Getxy(&xx, &yy);
  46.     MkAskBox(FootPrint,    28, 11,    26, 3, 'L', "[ ASCII Value ]",
  47.        "[ <ESC>    to Cancel ]", "Enter Three Digits: ", 0x4E);
  48.  
  49.  /* Catch Response, Build Character & Split */
  50.     while (n &&    (c = Kbq_read()) != ESC    && c !=    CR)
  51.        if (isdigit(c)) { ch = 10 * ch +    c - '0'; n--; DputChr(c, 0x4E);    }
  52.     ZapAskBox(FootPrint, 28, 11, 26, 3,    'L'); Gotoxy(xx, yy); ShowCursor(1);
  53.     if (c IS ESC) return 0; else return    ch & 0xFF;
  54. }
  55.  
  56. -------------------------------------------------------------------------
  57.  
  58. >BaseName.  Return a Pointer to    the Name.Ext portion of    a Full Path.
  59.  
  60. char *BaseName(char *FileName)
  61. {
  62.     char *tp1;
  63.     
  64.     if ((tp1 = strrchr(FileName, BKSL))    != NULL) return    ++tp1;
  65.     if ((tp1 = strrchr(FileName, COLON)) != NULL) return ++tp1;
  66.     return FileName;
  67. }
  68.  
  69. -------------------------------------------------------------------------
  70.  
  71. >Beep.  Sound Tone for Specified Duration (in milliSeconds).
  72.  
  73. void Beep(unsigned int pitch, unsigned int Duration)
  74. { sound(pitch);    delay(Duration); nosound(); }
  75.   
  76. -------------------------------------------------------------------------
  77.  
  78. >Box.  Draw/Clr    a Single Line Box on the Screen.          [CGU-273]
  79.  
  80. void Box(int Left, int Top, int    Right, int Bottom, int Fill, int Color)
  81. /* Draw    a single line box using    Color &    Clear it to Fill. */
  82. {
  83.     int    i;
  84.     char Lid[81];
  85.  
  86.     Dwrite(Left, Top, Color, "┌"); Dwrite(Right, Top, Color, "┐");
  87.     Dwrite(Left, Bottom, Color,    "└"); Dwrite(Right, Bottom, Color, "┘");
  88.     *Lid = NULL; PadRight(Lid, '─', Right - Left - 1);
  89.     Dwrite(Left+1, Top,    Color, Lid); Dwrite(Left+1, Bottom, Color, Lid);
  90.     for    (i= Top    + 1; i < Bottom; i++) {
  91.     Dwrite(Left, i, Color, "│"); Dwrite(Right,    i, Color, "│");    }
  92.     ClrBox(++Left, ++Top, --Right, --Bottom, Fill);
  93. }
  94.  
  95. -------------------------------------------------------------------------
  96.  
  97. >CcolorSet.  Change the    Color of a Column of Characters.     [CGU-273]
  98.  
  99. void CcolorSet(int X, int Y, int Color,    int N)
  100. { while    (N--) if (Y < 26) SetAttr(X, Y++, Color); }
  101.  
  102. -------------------------------------------------------------------------
  103.  
  104. >CgaSnowFence.  Activate ReTrace Waiting on Video RAM Access.
  105.  
  106. void CgaSnowFence(void)    { SnowStop++; }
  107.  
  108. -------------------------------------------------------------------------
  109.  
  110. >Clr.  Clear Entire Screen to a    Specified Color.
  111.  
  112. #define    Clr(x)            (ClrBox(1, 1, 80, 25, x))
  113.  
  114. -------------------------------------------------------------------------
  115.  
  116. >ClrTo.  Clears    a Row to a Specified Point.
  117.  
  118. void ClrTo(int X, int Color)
  119. /* Clear from the current cursor location thru X. */
  120. {
  121.     int    xx, yy;
  122.     
  123.     Getxy(&xx, &yy); if    (X < xx) return; Scroll(xx, yy,    X, yy, Color, 0, 0);
  124. }
  125.  
  126. -------------------------------------------------------------------------
  127.  
  128. >ClrBox.  Clear    a Retangular Area to a Specified Color.
  129.  
  130. #define    ClrBox(a,b,c,d,x)    (Scroll(a, b,    c, d, x, 0, 0))
  131.  
  132. -------------------------------------------------------------------------
  133.  
  134. >CursorBwd.  Left Arrow    Action w/ Wrap Upwards.              [CGU-273]
  135.  
  136. void CursorBwd(int N)
  137. /* Move    the cursor N cols to the left */
  138. {
  139.     int    xx, yy;
  140.  
  141.     Getxy(&xx, &yy);
  142.     if ((xx -= (N % 80)) < 1) {    xx -= 80; if (--yy < 1)    yy = 25; }
  143.     Gotoxy(xx, yy);
  144. }
  145.  
  146. -------------------------------------------------------------------------
  147.  
  148. >CursorDn.  Down Arrow Action w/ Wrap.                  [CGU-273]
  149.  
  150. void CursorDn(int N)
  151. /* Move    the down N rows    & wrap to top if the cursor is on the last row */
  152. {
  153.     int    xx, yy;
  154.     
  155.     Getxy(&xx, &yy); if    ((yy +=    (N % 25)) > 25)    yy -= 25; Gotoxy(xx, yy);
  156. }
  157.  
  158. -------------------------------------------------------------------------
  159.  
  160. >CursorFwd.  Right Arrow Action    w/ Wrap    Downward.          [CGU-273]
  161.  
  162. void CursorFwd(int N)
  163. /* Move    the cursor N cols to the right */
  164. {
  165.     int    xx, yy;
  166.  
  167.     Getxy(&xx, &yy);
  168.     if ((xx += (N % 80)) > 80) { xx = 1; if (++yy > 25)    yy = 1;    }
  169.     Gotoxy(xx, yy);
  170. }
  171.  
  172. -------------------------------------------------------------------------
  173.  
  174. >CursorNL.  Perform a CR/LF Action w/ Wrap.              [CGU-273]
  175.  
  176. void CursorNL(int N) 
  177. /* Move    the cursor to the beginning of the next    row  */
  178. {
  179.     int    xx, yy;
  180.     
  181.     Getxy(&xx, &yy); if    ((yy +=    (N % 25)) > 25)    yy = 1;    Gotoxy(0, yy);
  182. }
  183.  
  184. -------------------------------------------------------------------------
  185.  
  186. >CursorUP.  Up Arrow Aaction w/    Wrap.                  [CGU-273]
  187.  
  188. void CursorUP(int N)
  189. /* Move    the cursor N rows up */
  190. {
  191.     int    xx, yy;
  192.  
  193.     Getxy(&xx, &yy); if    ((yy -=    (N % 25)) < 1) yy = 25;    Gotoxy(xx, yy);
  194. }
  195.  
  196. -------------------------------------------------------------------------
  197.  
  198. >DputChr.  Direct Write    a Character at Cursor w/ Update.
  199.  
  200. void DputChr(char ch, int Color)
  201. {
  202.     int    xx, yy;
  203.  
  204.     Getxy(&xx, &yy); Vpoke(Vaddr(xx,yy), ch + (Color <<    8)); CursorFwd(1);
  205. }
  206.  
  207. -------------------------------------------------------------------------
  208.  
  209. >Dread.  Copy N    Characters to a    String Starting    at (X,Y).
  210.  
  211. void Dread(int X, int Y, char *Text, int N)
  212. {
  213.     int    Addr;
  214.  
  215.     Addr = Vaddr(X, Y);
  216.     for    (*Text = NULL; N-- && X++ < 80;    *Text =    NULL, Addr += 2)
  217.     *Text++    = Vpeek(Addr) &    0xFF;
  218. }
  219.  
  220. -------------------------------------------------------------------------
  221.  
  222. >Dwrite.  Paint    a String at X,Y    w/ Color w/ Update.
  223.   
  224. void Dwrite(int    X, int Y, int Color, char *Text)
  225. {
  226.     int     addr;
  227.  
  228.     Color = Color << 8;    Gotoxy(X, Y); CursorFwd(strlen(Text));
  229.     for    (addr =    Vaddr(X, Y); *Text; addr += 2)
  230.        Vpoke(addr, (*Text++ & 0xFF) + Color);
  231. }
  232.  
  233. -------------------------------------------------------------------------
  234.  
  235. >DwriteEnd.  Dwrite w/ Pad to Fill "n" Spaces.
  236.  
  237. void DwriteEnd(int X, int Y, int Color,    char *Text, int    N)
  238. {
  239.     int     addr;
  240.  
  241.     Color = Color << 8;    Gotoxy(X, Y); CursorFwd(strlen(Text));
  242.     for    (addr =    Vaddr(X, Y); *Text; addr += 2, --N)
  243.        Vpoke(addr, (*Text++ | Color));
  244.     for    (Color |= ' '; N--; addr += 2) Vpoke(addr, Color);
  245. }
  246.  
  247. -------------------------------------------------------------------------
  248.  
  249. >ExpandTabs.  Explode Tabs into    Spaces ala X3.64/DEC/DOS.
  250.  
  251. void ExpandTabs(char *Text)
  252. {
  253.     int    i;
  254.     
  255.     for    (i = 0;    Text[i]; i++)
  256.        if (Text[i] IS HT) { 
  257.       Text[i++] = SPACE; OpenStr(Text + i, (8 - (i % 8)) % 8); }
  258. }
  259.  
  260. -------------------------------------------------------------------------
  261.  
  262. >FileExists.  TRUE if File is Found.                   [CGU-273]
  263.  
  264. int FileExists(char *FileName)
  265. /* Check to see    of a Find exists. RETURN 1 if exist 0 if not. */
  266. {
  267.     struct ffblk fb;
  268.     
  269.     return !findfirst(FileName,    &fb, 0);
  270. }
  271.  
  272. -------------------------------------------------------------------------
  273.  
  274. >GetaKey.  Wait    for a Keystroke    in a List (or Esc).        [CGU-273]
  275.  
  276. int GetaKey(unsigned char *List, int CaseLess)
  277. /* Wait    until one of the charaacters in    the list (or Esc) is pressed. */
  278. {
  279.     int    c;
  280.     
  281.     if (CaseLess) strupr(List);
  282.     do {
  283.        c = Kbq_read(); if (CaseLess) c = toupper(c);
  284.     } while (c != 27 &&    strchr(List, c)    == NULL);
  285.     return c;
  286. }
  287.  
  288. -------------------------------------------------------------------------
  289.  
  290. >GetAttr.  Report the Color (attribute)    of Chr at (X, Y).
  291.  
  292. #define    GetAttr(x,y)        (Vpeek(Vadr(X, Y)) >> 8)
  293.  
  294. -------------------------------------------------------------------------
  295.  
  296. >GetLineN.  Pull a Specified Line from a Text File.
  297.  
  298.    Valid Line Numbers range 1 -    32767.
  299.    Returns TRUE    if Line    Exists.     Sets Line = "~" & Returns FALSE otherwise.
  300.    To Open/ReOpen File:    GetLineN(FileName, 0);
  301.    To Close File:    GetLineN(NULL, 0);
  302.  
  303. int GetLineN(char *Line, int Which1)
  304. {
  305.     static int LastKnownLine    = 0;
  306.     static int LineInc        = 1;
  307.     static int NextLine        = 0;
  308.     static int EOFatLine    = 32500;
  309.     static long    Lines[501];    /* List    of File    Jump Pointers */
  310.     static FILE    *fp = NULL;
  311.     int    c, i, j;
  312.     char *tp1;
  313.  
  314.  /* IF Initialize/Close    */
  315.     if (Which1-- < 1) {
  316.        if (fp != NULL) fclose(fp); EOFatLine = 32500;
  317.        NextLine    = LastKnownLine    = 0; LineInc = 1; Lines[0] = 0L; 
  318.        if (Line    != NULL    && *Line && (fp    = fopen(Line, "r")) IS NULL) 
  319.       return FALSE;
  320.        return TRUE;
  321.      }
  322.      
  323.  /* If Within Known Range */
  324.     if (Which1 <  0 || Which1 >= EOFatLine) { 
  325.        strcpy(Line,"~"); return    FALSE; }
  326.     if (Which1 < LastKnownLine)    {
  327.        if (Which1 != NextLine) {
  328.       i = Which1 / LineInc;    fseek(fp, Lines[i], SEEK_SET);
  329.       i = Which1 % LineInc;
  330.        } else i    = 0;
  331.        for ( ; i >= 0; i--) fgets(Line,    255, fp);
  332.        Line[strlen(Line)-1] = NULL; NextLine = ++Which1;
  333.        return TRUE;
  334.     }
  335.  
  336.  /* Not    in Known Range */
  337.     i =    LastKnownLine /    LineInc;
  338.     if (Which1 != NextLine) {
  339.        fseek(fp,Lines[i],SEEK_SET); LastKnownLine = i *    LineInc; }
  340.     while (LastKnownLine <= Which1) {
  341.        if (fgets(Line, 255, fp)    IS NULL) {
  342.       EOFatLine=LastKnownLine; strcpy(Line,    "~"); return FALSE; }
  343.        if (++LastKnownLine % LineInc IS    0) {
  344.       Lines[++i] = ftell(fp);
  345.       if (i    IS 500)    {        /* OverFlow -->    Crunch List */
  346.          LineInc *=    2; for (i = 1; i <= 250; i++) Lines[i] = Lines[2*i];
  347.          i = 250;
  348.       }
  349.        }
  350.     }
  351.     Line[strlen(Line)-1] = NULL; NextLine = LastKnownLine; return TRUE;
  352. }
  353.  
  354. ---------------------------------------------------------------------------
  355.  
  356. >GetLongDate.  Report Today as YYMMDD.                   [CGU-273]
  357.  
  358. long int GetLongDate(void)
  359. /* Return: The current date in the format YYMMDD. */
  360. {
  361.     struct date    today;
  362.     char Text[40];
  363.  
  364.     getdate(&today);
  365.     sprintf(Text, "%2.2d%2.2d%2.2d", today.da_year - 1900,
  366.        today.da_mon, today.da_day);
  367.     return atol(Text);
  368. }
  369.  
  370. -------------------------------------------------------------------------
  371.  
  372. >GetxKey.  Report a Keystroke as either    ascii or ScanCode * 256.  [CGU-273]
  373.  
  374. unsigned int GetxKey(void)
  375. /* return an ascii value or 256    * ScanCode */
  376. {
  377.     union REGS rg;
  378.  
  379.     while (1) {
  380.        rg.h.ah = 1; int86(0x16,    &rg, &rg);
  381.        if (rg.x.flags &    0x40) {    int86(0x28, &rg, &rg); continue; }
  382.        rg.h.ah = 0; int86(0x16,    &rg, &rg);
  383.        if (rg.h.al == 0) return    rg.h.ah    << 8; else return rg.h.al;
  384.     }
  385. }
  386.  
  387. -------------------------------------------------------------------------
  388.  
  389. >Getxy.  Returns the Current Cursor Location & TRUE if Visible.     [CGU-273]
  390.  
  391. int Getxy(int *X, int *Y)
  392. {
  393.     union REGS rg;
  394.  
  395.     rg.h.bh = 0; rg.h.ah = 3; int86(0x10, &rg, &rg);
  396.     *X = rg.h.dl + 1; *Y = rg.h.dh + 1;
  397.     return !(rg.h.ch & 0x20);        /* True if Cd_Cursor */
  398. }
  399.  
  400. -------------------------------------------------------------------------
  401.  
  402. >GetFileSize.  Report File Size    in Bytes or EOF.           [CGU-273]
  403.  
  404. long GetFileSize(char *FileName)
  405. {
  406.     struct ffblk fb;
  407.  
  408.     if(!findfirst(FileName, &fb, 0)) return (fb.ff_fsize); else    return (-1);
  409. }
  410.  
  411. -------------------------------------------------------------------------
  412.  
  413. >Gotoxy.  Relocate the Cursor to (X, Y).             [CGU-273]
  414.  
  415. void Gotoxy(X, Y)
  416. /* RePosition cursor to    (X, Y) */
  417. {
  418.     union REGS rg;
  419.  
  420.     rg.h.ah = 2; rg.h.dh = --Y;    rg.h.dl    = --X; rg.h.bh = 0;
  421.     int86(0x10,    &rg, &rg);
  422. }
  423.  
  424. -------------------------------------------------------------------------
  425.  
  426. >HideCursor.  Make Cursor Invisible & Report if    it Was ON.
  427.  
  428. int HideCursor(void)
  429. /* Turn    the cursor off */
  430. {
  431.     int    Visible;
  432.     union REGS rg;
  433.  
  434.     rg.h.bh = 0;     rg.h.ah = 3; int86(0x10, &rg, &rg);
  435.     if ((Visible = !(rg.h.ch & 0x20)) != 0) {
  436.        rg.h.ch |= 0x20;    rg.h.ah    = 1; int86(0x10, &rg, &rg); }
  437.     return Visible;
  438. }
  439.  
  440. -------------------------------------------------------------------------
  441.  
  442. >InsChr.  Post a Character in Front of a String.
  443.  
  444. #define    InsChr(x,y)        (PadLeft(x, y, strlen(x) +    1))
  445.  
  446. -------------------------------------------------------------------------
  447.  
  448.    Kbq_x() are taken from "Controlling The Keyboard Buffer" by Steven Gruel
  449. (The C Users Journal 7/90, pgs 85-6) w/    modifactions by    EK to return Keys.h
  450. values for Extented Characters.     These can be used in TSRs, unlike the 
  451. routines in <conio.h>.
  452.  
  453. ---> Background, the Keyboard Queue consists of    16 (16 bit) words located at
  454. 0x40:0x1E.  It is a Circular Buffer w/ Read Pointer at 0x40:0x1A (KBQRD)
  455. and Write Pointer at 0x40:0x1C (KBQWRT).
  456.  
  457. #include <dos.h>
  458. #define    KBQSEG    0x40
  459. #define    KBQRD    0x1A
  460. #define    KBQWRT    0x1C
  461. #define    KBQBTM    0x1E
  462. #define    KBQTOP    0x3E
  463.  
  464. >Kbq_flush.  Zip Contents of Keyboard Queue.
  465.  
  466. void Kbq_flush(void) { poke(KBQSEG, KBQWRT, peek(KBQSEG, KBQRD)); }
  467.  
  468. -------------------------------------------------------------------------
  469.  
  470. >Kbq_poll.  A getch() w/ Keys.h    Reporting.  No Wait (returns 0)
  471.  
  472. int Kbq_poll(void)
  473. {            /* Returns chr, Keys.h code    or Zero.  No Wait. */
  474.     if (peek(KBQSEG, KBQWRT) ==    peek(KBQSEG,KBQRD)) return 0;
  475.     return Kbq_read();
  476. }
  477.  
  478. -------------------------------------------------------------------------
  479.  
  480. >Kbq_read.  A getch() w/ Keys.h    Reporting.  Waits for User.
  481.  
  482. int Kbq_read(void)
  483. {
  484.     int    c = 0;
  485.     union REGS rg;
  486.  
  487.     do {
  488.        rg.h.ah    = 1; int86(0x16, &rg, &rg);
  489.        if (rg.x.flags &    0x40) {    int86(0x28, &rg, &rg); continue; }
  490.        rg.h.ah = 0; int86(0x16,    &rg, &rg);
  491.        if (rg.h.al == 0) c = rg.h.ah | 128; else c = rg.h.al;
  492.     } while (c == 0);
  493.     return(c);
  494. }
  495.  
  496. -------------------------------------------------------------------------
  497.  
  498. >Kbq_snoop.  Reports Nth Chr$ ala Keys.h.  Queue is Not    Altered.
  499.  
  500. int Kbq_snoop(int Which1)
  501. {      /* Report the    "Nth" Keystroke    in Queue.  (w/o    Removal). */
  502.     int    i, Fill, Empty,    Keystroke;
  503.  
  504.     Fill = peek(KBQSEG,    KBQWRT);  Empty    = peek(KBQSEG,KBQRD);
  505.     if (Fill ==    Empty) return 0;
  506.     if ((i = Fill - Empty) < 0)    i += 32; if ((Which1 *=    2) > i)    return 0;
  507.     if ((i = Empty + Which1 - 2) >= KBQTOP) i -= 32;
  508.     Keystroke =    peek(KBQSEG, i);
  509.     if ((Keystroke & 127) == 0)    return ((Keystroke >> 8) | 128);
  510.     return (Keystroke &    127);
  511. }
  512.  
  513. -------------------------------------------------------------------------
  514.  
  515. >Kbq_stuff.  Stuffs a Keys.h Keypunch into the Keyboard    Queue.
  516.  
  517. int Kbq_stuff(unsigned char ch)
  518. {
  519.  /* Shove a Keystroke Into Keyboard Queue. */
  520.     int    Fill, KeyStroke;
  521.  
  522.     if (!ch) return 0;
  523.     if (ch < 128) KeyStroke = ch; else KeyStroke = (ch & 127) << 8;
  524.     Fill = peek(KBQSEG,    KBQWRT); poke(KBQSEG, Fill, KeyStroke);
  525.     if ((Fill += 2) >= KBQTOP) Fill = KBQBTM;
  526.     if (Fill ==    peek(KBQSEG,KBQRD)) return 0;    /* Full */
  527.     poke(KBQSEG, KBQWRT, Fill);    return 1;
  528. }
  529.  
  530. -------------------------------------------------------------------------
  531.  
  532. >Kbq_tally.  Reports 0-15 Keypunches Waiting in    Queue.
  533.  
  534. int Kbq_tally(void)
  535. {    /* Report Number of Keystrokes in Queue. */
  536.     int    i;
  537.  
  538.     i =    (peek(KBQSEG, KBQWRT) -    peek(KBQSEG,KBQRD)) / 2;
  539.     if (i < 0) return i    + 16;  else return i;
  540. }
  541.  
  542. -------------------------------------------------------------------------
  543.  
  544. >LPrintChr.  Print a character on a Specifed printer.        [CGU-273]
  545.  
  546. int LPrintChr(char ch, int lptnum) { return biosprint(0, ch, --lptnum) & 0x29; }
  547.  
  548. -------------------------------------------------------------------------
  549.  
  550. >LPreset.  Reset the Specified Printer.                [CGU-273]
  551.  
  552. int LPreset(int    lptnum)    { return !(biosprint(1,    0, --lptnum) & 0x29); }
  553.  
  554. -------------------------------------------------------------------------
  555.  
  556. >LPbusy.  Check    Busy Flag for Specified    Printer.        [CGU-273]
  557.  
  558. int LPready(int    lptnum)    { return !(biosprint(2,    0, --lptnum) & 0x40); }
  559.  
  560. -------------------------------------------------------------------------
  561.  
  562. >LPrintStr.  Lay down a    String on a Printer (no    CR/LF).        [CGU-273]
  563.  
  564. int LPrintStr(char *str, int lptnum)
  565. {
  566.     for    (lptnum--; *str; str++)
  567.        if (biosprint(0,    *str, lptnum) &    0x29) return 0;
  568.     return 1;
  569. }
  570.  
  571. -------------------------------------------------------------------------
  572.  
  573. >LTrim.  Crop WhiteSpace from the Front    of a String.
  574.  
  575. #define    LTrim(x)        (TrimStr(x, 1))
  576.  
  577. -------------------------------------------------------------------------
  578.  
  579. >MkAskBox.  Construct a    Query Box on the CRT w/    optional Shadow    & Save.
  580.  
  581. void MkAskBox(char *FootPrint, int X, int Y, int Width,    int Tall, char Shadow,
  582.     char *TopTitle, char *FootTitle, char *Prompt, BYTE    Color)
  583. {
  584.     int    Xc, Xsh, Xg, Y1, X1;
  585.  
  586.  /* Handle Shadow */
  587.     X1 = X + Width - 1;    Y1 = Y + Tall -    1; Xg =    Xsh = X;
  588.     if (Y+Tall > 25);
  589.     else if (Shadow IS 'L' && X    > 1)   { Xsh--;    Xg--; Y1++; }
  590.     else if (Shadow IS 'R' && X    < 80)  { Xsh++;    X1++; Y1++; }
  591.  
  592.  /* Build Window w/ Titles */
  593.     HideCursor(); if (FootPrint    != NULL) SaveBox(Xg, Y,    X1, Y1,    FootPrint);
  594.     Box(X, Y, (X1 = X+Width-1),    (Y1 = Y+Tall-1), Color,    Color);
  595.     if (Shadow)    MkShadow(X, Y, X1, Y1, Shadow);
  596.     if (*TopTitle) Dwrite(X+(Width-strlen(TopTitle)+1)/2, Y, Color, TopTitle);
  597.     if (*FootTitle)
  598.        Dwrite (X+(Width-strlen(FootTitle)+1)/2,    Y1, Color, FootTitle);
  599.     if (*Prompt) Dwrite(X+1, Y+1, Color, Prompt); else Gotoxy(X+1, Y+1);
  600.     ShowCursor(0);
  601. }
  602.  
  603. -------------------------------------------------------------------------
  604.  
  605. >MkShadow.  Create the illusion    of a R/L Shadow.         [CGU-273]
  606.  
  607. void MkShadow(int Left,    int Top, int Right, int    Bottom,    char Which1)
  608. /* Create the illusion of a shadow under the specified window */
  609. {
  610.     int    X, Y, Z;
  611.  
  612.     if (++Bottom > 25) return;
  613.     if (Which1 == 'L' && --Left    < 1) return;
  614.     if (Which1 != 'L' && ++Right > 80) return;
  615.     if ((Z = Bottom - Top++) < 1) return;
  616.     if (Which1 == 'L') CcolorSet(Left, Top, 0, Z);
  617.     else CcolorSet(Right, Top, 0, Z);
  618.     if ((Z = Right - Left) < 1)    return;
  619.     RcolorSet(Left, Bottom, 0, Z);
  620. }
  621.  
  622. -------------------------------------------------------------------------
  623.  
  624. >NewExt.  Create a New File Name from an Old One & a New .Ext
  625.  
  626. void NewExt(char *Old, char *New, char *Ext)
  627. {
  628.     char *tp1;
  629.  
  630.     strcpy(New,    Old); if ((tp1 = strrchr(New, DOT)) != NULL) *tp1 = NULL;
  631.     if (!*Ext) return;
  632.     strcat(New,    "."); if (*(tp1    = Ext) IS DOT) tp1++; strcat(New, tp1);
  633. }
  634.  
  635. -------------------------------------------------------------------------
  636.  
  637. >OpenStr.  SHift Text Right, Padd w/ Spaces, Retain Everything.
  638.  
  639. #define    OpenStr(x,y)        (PadLeft(x, SPACE, strlen(x) + y))
  640.  
  641. -------------------------------------------------------------------------
  642.  
  643. >PadEnds.  Center Text by Alternate Fore/Aft Pads.
  644.  
  645. void PadEnds(char *Text, int ch, int N)
  646. {
  647.    if (*Text) PadLeft(Text, ch,    (N + strlen(Text)) / 2);
  648.    PadRight(Text, ch, N);
  649. }
  650.  
  651. -------------------------------------------------------------------------
  652.  
  653. >PadLeft.  PreAppend enough of a Specified Chr to make a Specified Length.
  654.  
  655. void PadLeft(char *Text, int ch, int N)
  656. {
  657.     if (N > strlen(Text)) {
  658.        strrev(Text); PadRight(Text, ch,    N); strrev(Text); }
  659. }
  660.  
  661. -------------------------------------------------------------------------
  662.  
  663. >PadRight.  Append enough of a Specified Chr to    make a Specified Length.
  664.  
  665. void PadRight(char *Text, int ch, int N)
  666. {
  667.     if ((N -= strlen(Text)) > 0) {
  668.        for (Text += strlen(Text); N--; ) *Text++ = ch; *Text = NULL; }
  669. }
  670.  
  671. -------------------------------------------------------------------------
  672.  
  673. >PopHelp.  Pop Up Help Window (60 Chr Wide) w/ MORE & PgUp.
  674.  
  675. void PopHelp(char **PopHelpPtr)
  676. {
  677.     int    i, j, xx, yy, Flag;
  678.     char   **dp, FootPrint[2810];
  679.  
  680.     Getxy(&xx, &yy);
  681.     for    (i = 2,    dp = PopHelpPtr; *dp; dp++) i++; if (i > 22) i = 22;
  682.     Flag = HideCursor();
  683.     MkAskBox(FootPrint,    5, 2, 60, i, 'L', "", "[ Hit Any Key ]", "", 0x0A);
  684.     HideCursor();
  685.     for    (dp = PopHelpPtr, j = 3; *dp; dp++) {
  686.        Dwrite(6, j, 0x0A, *dp);
  687.        if (++j IS 22 ||    dp[1] IS NULL) {
  688.       if (dp[1] !=    NULL) Dwrite(6,    j, 0x0A, "--- More --- ");
  689.       switch (Kbq_read()) {
  690.       case    ESC:  j    = EOF; break;
  691.       case PGUP:
  692.          if    ((dp -=    18) < PopHelpPtr + 10) dp = PopHelpPtr + 9;
  693.       default:   if (dp[1]    != NULL) dp -= 10;
  694.       }
  695.       if (j IS EOF) break;    j = 3; ClrBox(6, 3, 63,    22, 0x0A);
  696.        }
  697.     }
  698.     ZapAskBox(FootPrint, 5, 2, 60, i, 'L'); Gotoxy(xx, yy);
  699.     if (Flag) ShowCursor(0);
  700. }
  701.  
  702. -------------------------------------------------------------------------
  703.  
  704. >Query.  A User    Interactive "Dialogue" Box. 
  705.  
  706. CaseLess Flag: 0:Nml, 1:CaseLess, -1:Numeric Only, -2:CaseLess/NoSpaces.
  707.  
  708. int Query(char *Text, char *TopTitle, int CaseLess, BYTE Color,
  709.    char    **Help2Pop)
  710. {
  711.     int    c, xx, yy;
  712.     char *tp1, FootPrint[488];
  713.  
  714.  /* Establish Window */
  715.     tp1    = Text;    Getxy(&xx, &yy);
  716.     MkAskBox(FootPrint,    5, 10, 60, 3, 'L', TopTitle,
  717.       "[ <Esc> to Cancel ]", Text,    Color);
  718.     while ((c =    Kbq_read()) != CR) {
  719.        if (CaseLess) c = toupper(c);
  720.        if (c IS    ESC) { *Text = NULL; Text[1] = ESC; break; }
  721.        else if (c IS BS) {
  722.       if (tp1 IS Text) {
  723.          if (!strlen(Text)) continue; tp1 += strlen(Text);    }
  724.       tp1--; c = NULL; }
  725.        else if (c IS F1    && Help2Pop != NULL) { PopHelp(Help2Pop); continue; }
  726.        else if (c IS F2) c = AnyCharacter();
  727.        else if (CaseLess IS -1)    { if (!isdigit(c)) continue; }
  728.        else if (CaseLess IS -2 && c IS SPACE) continue;
  729.        else if (!iscntrl(c) && isascii(c));
  730.        else continue;
  731.        if (c &&    strlen(Text) < 57) *tp1++ = c; *tp1 = NULL;
  732.        DwriteEnd(6, 11,    Color, Text, 57);
  733.     }
  734.     ZapAskBox(FootPrint, 5, 10,    60, 3, 'L'); Gotoxy(xx,    yy); ShowCursor(1);
  735.     return !(!*Text && Text[1] IS ESC);
  736. }
  737.  
  738. -------------------------------------------------------------------------
  739.  
  740. >RcolorSet.  ReColor a Row of Text N characters    Long.         [CGU-273]
  741.  
  742. void RcolorSet(int X, int Y, int Color,    int N)
  743. {
  744.     int    addr;
  745.  
  746.     Color <<= 8;
  747.     for    (addr =    Vaddr(X, Y); N--; addr += 2)
  748.     Vpoke(addr, Vpeek(addr)    & 0xFF + Color);
  749. }
  750.  
  751. -------------------------------------------------------------------------
  752.  
  753. >Remove.  Zip all apperances of    a Specified Chr.
  754.  
  755. void Remove(char *Text,    int ch)
  756. { while    ((Text = strchr(Text, ch)) != NULL) strcpy(Text, Text +    1); }
  757.  
  758. -------------------------------------------------------------------------
  759.  
  760. >RepeatChr.  Build a String of Specified Length    from a Specified Chr.
  761.  
  762. void RepeatChr(char *Target, int ch, int N)
  763. { *Target = NULL; PadRight(Target, ch, N); }
  764.  
  765. -------------------------------------------------------------------------
  766.  
  767. >RestoreBox.  Restore an Area of the CRT from an Array.
  768.  
  769. void RestoreBox(int Left, int Top, int Right, int Bottom, char *FootPrint)
  770. {
  771.     int    i, X, Y, Addr;
  772.  
  773.     for    (Y = Top; Y <= Bottom; Y++) {
  774.        Addr = Vaddr(Left, Y);
  775.        for (X =    Left; X++ <= Right; Addr += 2) {
  776.       i = *FootPrint++ & 0xFF; i |= *FootPrint++ << 8; Vpoke(Addr,    i); }
  777.     }
  778. }
  779.  
  780. -------------------------------------------------------------------------
  781.  
  782. >RTrim.  Aft Crop WhiteSpace from a String.
  783.  
  784. #define    RTrim(x)        (TrimStr(x, 2))
  785.  
  786. -------------------------------------------------------------------------
  787.  
  788. >Sar.  Search &    Replace    one SubStr w/ Another N    times.
  789.  
  790. int Sar(char *Text, char *This,    char *That, int    StopAfter)
  791. {
  792.     int    i, j, k, n = 0;
  793.  
  794.     if (!StopAfter || (i = strlen(This)) IS 0) return 0; j = strlen(That);
  795.     if (strstr(That, This) != NULL) return 0;
  796.     for    (Text =    strstr(Text, This); n <    StopAfter && Text != NULL; n++)    {
  797.        strcpy(Text, Text + i);
  798.        if (j) {    Strrcpy(Text+j,    Text); memcpy(Text, That, j); }
  799.        Text = strstr(Text, This);
  800.     }
  801.     return n;
  802. }
  803.  
  804. -------------------------------------------------------------------------
  805.  
  806. >SaveBox.  Grab    a Portion of the CRT into an Array.
  807.  
  808. void SaveBox(int Left, int Top,    int Right, int Bottom, char *FootPrint)
  809. {
  810.     int    i, X, Y, Addr;
  811.  
  812.     for    (Y = Top; Y <= Bottom; Y++) {
  813.        Addr = Vaddr(Left, Y);
  814.        for (X =    Left; X++ <= Right; Addr += 2) {
  815.       *FootPrint++ = (i = Vpeek(Addr)) & 0xFF;
  816.       *FootPrint++    = i >> 8;
  817.        }
  818.     }
  819. }
  820.  
  821. -------------------------------------------------------------------------
  822.  
  823. >Scroll.  Scroll a Box Up/Down N Lines.                   [CGU-273]
  824.  
  825. void Scroll(int    Left, int Top, int Right, int Bottom, int Color, int N,    
  826.    int Flag)
  827. {
  828.    union REGS rg;
  829.  
  830.    rg.h.bh = Color; rg.h.cl = --Left; rg.h.ch =    --Top; rg.h.dl = --Right;
  831.    rg.h.dh = --Bottom; rg.h.al = N; rg.h.ah = 7    - !Flag; int86(0x10,&rg,&rg);
  832. }
  833.  
  834. -------------------------------------------------------------------------
  835.  
  836. >SetAttr.  Set the Cell    at X, Y    to Color.
  837.  
  838. void SetAttr(int X, int    Y, int Color)
  839. {
  840.     int    Addr;
  841.   
  842.     Addr = Vaddr(X, Y);    
  843.     Vpoke(Vaddr(X, Y), (Vpeek(Addr) & 0xFF) | (Color <<    8));
  844. }
  845.  
  846. -------------------------------------------------------------------------
  847.  
  848. >SetVideoMode.  Change the Current CRT Display Mode.        [CGU-273]
  849.  
  850. void SetVideoMode(int Mode)
  851. {
  852.     union REGS rg;
  853.     
  854.     rg.h.ah = 0x00; rg.h.al = Mode; int86(0x10,    &rg, &rg);
  855. }
  856.  
  857. -------------------------------------------------------------------------
  858.  
  859. >ShowCursor.  Unhide/Fatten/UnFattten Blinking Cursor.
  860.  
  861. void ShowCursor(int Fat)
  862. {
  863.     static int Virgin =    0;
  864.     union REGS rg;
  865.  
  866.     rg.h.bh = 0; rg.h.ah = 3; int86(0x10, &rg, &rg);    
  867.     if (!Virgin) Virgin    = rg.h.ch;
  868.     rg.h.ah = 1; rg.h.ch = 0; if (!Fat)    rg.h.ch    = Virgin;
  869.     rg.h.ch &= 0x1F; int86(0x10,&rg,&rg);
  870. }
  871.  
  872. -------------------------------------------------------------------------
  873.  
  874. >Strrcpy.  A strcpy run    Tail First.
  875.  
  876. void Strrcpy(char *Target, char    *Source)
  877. /* Target may be Inside    Source */
  878. {
  879.     int    N;
  880.  
  881.     for    (N = strlen(Source), Source += N, Target += N++; N--; )
  882.        *Target-- = *Source--;
  883. }
  884.  
  885. -------------------------------------------------------------------------
  886.  
  887. >Tally.  Report    Number of a Specified Chr in a String.
  888.  
  889. int Tally(char *Text, int ch)
  890. {
  891.     int    n;
  892.     
  893.     for(n = 0; (Text = strchr(Text, ch)) != NULL; n++) Text++;
  894.     return n;
  895. }
  896.  
  897. -------------------------------------------------------------------------
  898.  
  899. >TisHelp.  Access a Text-Index Scheme "Help" File.
  900.  
  901.    TIS is a simple idea    (this Manual is    done that way) using a Flag character 
  902. at the Left Margin (">") to denote Topic Keys.    Vu.Exe can create a ".LST" 
  903. file of    these keys as a    "Select    List".    (".  " delimits    the Topic Key).
  904.  
  905.    To Use TisHelp, strcpy() into the extern char HelpFileName[81] the name of 
  906. the File w/ your Help text.  Prior to calling TisHelp, strcpy()    the Topic Key 
  907. into the extern    char HelpTag[20].
  908.  
  909.    Some    routines use a "HelpKey" instead of trapping F1    directly.  For these, 
  910. set the    extern int HelpKey to some appropriate value, such as HelpKey =    F1;
  911.  
  912.  
  913. char HelpFileName[81], HelpTag[20];
  914. int HelpKey = 0;
  915.  
  916. void TisHelp(void)
  917. {
  918.     char Cmd[128];
  919.  
  920.     if (!*HelpFileName)    return;    Trim(HelpTag);
  921.     sprintf(Cmd, "VU /C1F301E /F \">%s\" %s", HelpTag, HelpFileName); 
  922.     system(Cmd);
  923. }
  924.  
  925. -------------------------------------------------------------------------
  926.  
  927. >TMu.  Pop a Menu Box w/ Up/Down Wrap, HiLite &    Hot Keys.
  928. int  TMu(char **Mu, int    X, int Y, long Colors, int Border);
  929.  
  930. char *Mu[] = {
  931.   " Menu #1  +    [ User Menu #1 ]",
  932. /*1234567HRM123456789012345678 -------> Ruler Line for Drop Menues */
  933.       "1A+       Option 1    ",
  934.       "2B+       Option 2    ",
  935.       "3C+       Option 3    ",
  936.       "       --------    ",
  937.       "4D+       Option 4    ",
  938.       "5E+       Option 5    ",
  939.       "6F+       Option 6    ",
  940.       NULL };
  941.  
  942.    How it Works:  TMu counts the number    of Option Entries in the Menu Array
  943. (seven in Mu[] above).    It then    counts the Characters in First Option &    Pops
  944. an AskBox in the Color "Border"    >> 8.  ("Grey Out" is "Border" & 0xFF).
  945.  
  946.    The "[]" and    all text between is pulled from    the Zeroth Option Line and
  947. used as    the Title for this Menu.
  948.  
  949.    Text    from the Option    Lines is Painted into the AskBox according to
  950. "Colors", HiLiting the First Line.  <0x1F4E17 prints Bright White on Blue 
  951. using Bright Yellow on Red as the HiLite and Dark Grey on Blue as "GrayOut">.  The 
  952. First Three Characters are Skipped.
  953.  
  954.    User    Input is used to relocate the HiLite Bar (it Wraps) until either
  955. <Enter>    is pressed or a    keystroke matching one of the "Hot Keys" listed    at
  956. the beginning of each Option Line.
  957.  
  958.    Only    those Options w/ "+" as    their Third (Mask) Character can be Selected.
  959.  
  960.    On matching a Hot Key or getting a valid Selection, TMu Zips    the Menu Box 
  961. and returns the    Second Character on the    Selected Line (or 0 on <Esc>).    For 
  962. the Above Mu[],    hitting    "4" or punching    <Enter>    with "Option 4"    HiLited    would 
  963. return "D".
  964.  
  965.    If F1 is pressed, the First 10 Characters of    Mu[0] are passed to TisHelp
  966. as a Tag.  TisHelp Crops Leading/Trailing Spaces on the    Tag before seaching.
  967.  
  968. ---------
  969.  
  970.    "Gray Out" Masking:    The Third (Mask) character on each Option Line 
  971. specifies whether the Option is    Selectable.  A "+" means it is.     A "-" means 
  972. it isn't (it is    curently "Greyed Out").     Blanks    never Grey Out or Select.
  973.  
  974.    If the eleventh character of    the Zeroth Line    is not a "+", the entire Menu 
  975. is "Greyed Out"    and no selections can be made (only <Esc> works>.
  976.  
  977. ---------
  978.  
  979.    The maximum number of Options is 21 (22 w/o TBar).  If TBar is Used,    the
  980. Above Mu[] can be used as a Guide.  Max    Option Text Width otherwise is 77.
  981. Menu Boxes Shadow Right.
  982.  
  983. int TMu(char **Mu, int X, int Y, long Color, int Border)
  984. {
  985.     int    ch, i, xx, yy, Flag, GreyOut, HiLite, Lit, Selected, Z;
  986.     char *FootPrint;
  987.     extern char    HelpTag[20];
  988.  
  989.  /* Save Cursor, Calculate Menu    Size & Get Colors */
  990.     Getxy(&xx, &yy); Flag = HideCursor(); if (Mu[0][10]    IS '+')    Border >>= 8;
  991.     GreyOut = Color & 0xFF; Color >>= 8; HiLite     = Color & 0xFF; Color >>= 8;
  992.     if (Mu[0][10] IS '-') Color    = GreyOut;
  993.     for    (Z = 1;    Mu[Z+1]    != NULL    ; Z++);
  994.     if ((FootPrint = (char *) malloc(strlen((Mu[1]) + Z+3) * 2)) IS NULL)
  995.        return 0;
  996.  
  997.  /* Build a Drop Box Menu */
  998.     MkAskBox(FootPrint,    X, Y, strlen(Mu[1])-1, Z+2, 'R',
  999.        (char *)    strchr(*Mu, '['), "[<Esc> to Cancel]", "", Border);
  1000.     for    (i = 0;    i++ < Z; )
  1001.     if (Mu[i][2] IS '-') Dwrite(X+1, Y+i, GreyOut,    Mu[i]+3);
  1002.     else Dwrite(X+1, Y+i, Color, Mu[i]+3);
  1003.     Lit    = Selected = 1;    Dwrite(X+1, Y+1, HiLite, Mu[1]+3); HideCursor();
  1004.  
  1005.  /* Querry User    */
  1006.     do {
  1007.        if (Selected != Lit) {
  1008.       if (Mu[Lit][2] IS '-') Dwrite(X+1, Y+Lit, GreyOut, Mu[Lit]+3);
  1009.       else Dwrite(X+1, Y+Lit, Color, Mu[Lit]+3);
  1010.       Lit =    Selected; Dwrite(X+1, Y+Lit, HiLite, Mu[Lit]+3);
  1011.        }
  1012.        switch (ch = Kbq_read())    {
  1013.        case F1:
  1014.       strncpy(HelpTag, Mu[0], 10); HelpTag[10] = NULL; TisHelp();
  1015.       break;
  1016.        case DN:      if (Selected++ IS Z) Selected    = 1; break;
  1017.        case UP:      if (Selected-- IS 1) Selected    = Z; break;
  1018.        case FWD:
  1019.        case BWD:
  1020.        case ESC:  Selected = ch    = 0; break;
  1021.        case CR:      if (Mu[Selected][2] IS '+') ch = 0; break;
  1022.        default:
  1023.       for (i = 0; ch != SPACE && i++ < Z; )
  1024.          if    (*Mu[i]    IS ch && Mu[i][2] IS '+') {
  1025.         ch = 0;    Selected = i; break; }
  1026.        }
  1027.     } while (ch);
  1028.  
  1029.  /* Clean Up & Split */
  1030.     ZapAskBox(FootPrint, X, Y, strlen(Mu[1])-1,    Z+2, 'R'); free(FootPrint);
  1031.     Gotoxy(xx, yy); if (Flag) ShowCursor(0);
  1032.     return (!Selected || Mu[0][2] IS '-') ? 0 :    Mu[Selected][1];
  1033. }
  1034.  
  1035. -------------------------------------------------------------------------
  1036.  
  1037. >TBarMu.  A 6-Zone Drop    Menu Bar w/ Title, Context Sensitive Help & Wrap.
  1038.  
  1039. char **Tbar[] =    { Mu1, Mu2, Mu3, Mu4, Mu5, Mu6,    NULL };
  1040.  
  1041.    TBarMu shells over the TMu scheme above converting a    set of 1-6 ordinary 
  1042. Mu[]'s into Drop Menus "Suspended" from    a Select Bar.
  1043.  
  1044.    Colors for the Bar, its HiLite and the Border of Dropped Menues (so they
  1045. will appear to be "attached") are set by "BarColors".  The Bar is constructed
  1046. by clearing the    Top Row    on the CRT and writing in the first 10 Characters from
  1047. the Zeroth Option on each Menu.     The "Title" Post at Column 60.
  1048.  
  1049.    The First "Hot Zone"    is HiLited.  Arrow Keys    shift the HiLite.  <Enter> or
  1050.  drops    the Menu for that Hot Zone allowing a Selection    to be Made.  Hitting
  1051. <Esc> "UnDrops"    a Menu or, if none is down, exits w/ a return value of ESC.
  1052.  
  1053.    F1 Pops Help    w/ the TisHelpTag for the HiLited Menu.
  1054.  
  1055.    When    a Valid    Selection is made on a Dropped Menu, it    returns    a non-zero
  1056. value indicating which Option was Selected.  TBarMu adds the Hot Zone
  1057. Number [1-6] (shifted left 8 places) to    this Return Value (Slot    #1 = 0x0100).  
  1058.  
  1059.    If a    Mu[] is    "Greyed    Out", it will not Drop.     "MuColor" is passed directly 
  1060. to TMu() to control the    Drop Box Mu Colors.  "BarColor"    has the    same format 
  1061. as MuColor: 0xNmHiGr where Nm is Normal, Hi is HiLite and Gr is    GreyOut.
  1062.  
  1063. For Example: 0x2F4E27 displays a Green Bar with    Bright White lettering,    a Red 
  1064. Select Bar with    Yellow lettering and Dark Grey on Green    for "Greyed Out" 
  1065. options.
  1066.  
  1067.  
  1068. int TBarMu(char    **TBar[], char *Title, long BarColor, long MuColor)
  1069. {
  1070.  /* Create & display a Menu Bar    (w/ Drop-Down Menues) &    Query User
  1071.   * Returns: (Slot# << 8) + Tag    Byte or    ESC for    hit ESC    on Bar Level.
  1072.   */
  1073.     int    i, xx, yy;
  1074.     int    HiLite,    GreyOut, Flag, Lit = 0,    Rtn, Slot = 0, Z;
  1075.     char FootPrint[321];
  1076.     extern char    HelpTag[20];
  1077.  
  1078.  /* Build Menu Bar */
  1079.     Getxy(&xx, &yy); Flag = HideCursor(); GreyOut = BarColor & 0xFF;
  1080.     HiLite = (BarColor >>= 8) &    0xFF; BarColor >>= 8;
  1081.     SaveBox(1, 1, 80, 1, FootPrint); Gotoxy(1,1); ClrTo(80, BarColor);
  1082.     for    (Z = 0;    TBar[Z]    != NULL; Z++) {
  1083.        strncpy(HelpTag,    TBar[Z][0], 10); HelpTag[10] = NULL;
  1084.        if (TBar[Z][0][10] IS '+') Dwrite(Z*10, 1, BarColor, HelpTag);
  1085.        else Dwrite(Z*10, 1, GreyOut, HelpTag);
  1086.        if (Z IS    5) break;
  1087.     }
  1088.     Dwrite(61, 1, BarColor, Title); RcolorSet(1, 1, HiLite, 10);
  1089.  
  1090.  /* Scroll Right/Left &    Pop Drop Menue(s) */
  1091.     for    (Rtn = 0; !Rtn;    ) {
  1092.        switch (Kbq_read()) {
  1093.        case F1:
  1094.       strncpy(HelpTag, TBar[Lit][0], 10); HelpTag[10] = NULL; TisHelp();
  1095.       break;
  1096.        case FWD: if (Slot++ IS Z) Slot = 0; break;
  1097.        case BWD: if (Slot-- IS 0) Slot = Z; break;
  1098.        case ESC: Rtn = ESC; break;
  1099.        case DN:
  1100.        case CR:
  1101.       if (TBar[Lit][0][10]    IS '+')    Rtn =
  1102.          TMu(TBar[Slot], 1+Slot*10,    2, MuColor, (BarColor << 8)+GreyOut);
  1103.       break;
  1104.        }
  1105.        if (Slot    != Lit)    {
  1106.       if (TBar[Lit][0][10]    IS '+')    RcolorSet(1+Lit*10, 1, BarColor, 10);
  1107.       else RcolorSet(1+Lit*10, 1, GreyOut, 10);
  1108.       Lit =    Slot; RcolorSet(1+Lit*10, 1, HiLite, 10);
  1109.        }
  1110.     }
  1111.  
  1112.  /* Clean Up & Split */
  1113.     RestoreBox(1, 1, 80, 1, FootPrint);    Gotoxy(xx, yy);
  1114.     if (Flag) ShowCursor(0); if    (Rtn IS    ESC) return ESC;
  1115.     return Rtn + (++Slot << 8);
  1116. }
  1117.  
  1118. -------------------------------------------------------------------------
  1119.  
  1120. >Trim.  Fore/Aft Crop WhiteSpeace from a String.
  1121.  
  1122. #define    Trim(x)            (TrimStr(x, 0))
  1123.  
  1124. -------------------------------------------------------------------------
  1125.  
  1126. >TrimStr.  The Business    End of the "Trim Trio" of Macros.
  1127.  
  1128. char *TrimStr(char *Text, int Flag)
  1129. {
  1130.     int    i;
  1131.  
  1132.     if (Flag > 2 || Flag < 0 ||    !*Text)    Flag = 0;
  1133.     if (!Flag || Flag >    1)
  1134.        while ((i = strlen(Text)    - 1) >=    0 && isspace(Text[i])) Text[i] = NULL;
  1135.     if (Flag < 2 && (i = strspn(Text, "    \t\n\f")) > 0) strcpy(Text, Text + i);
  1136.     return Text;
  1137. }
  1138.  
  1139. -------------------------------------------------------------------------
  1140.  
  1141. >Vpeek.  Directly Snatch 16 Bits from Video RAM.
  1142.  
  1143. int Vpeek(unsigned adr)
  1144. /* read    a character and    attribute from video RAM */
  1145. {
  1146.     if (!SnowStop) return peek(VSEG, adr);
  1147.     asm    push ds;
  1148.     _DX    = 986;                /* video status port */
  1149.     _DS    = VSEG;                /* video segment address */
  1150.     _SI    = adr;                /* video character offset */
  1151.     asm    cld;
  1152.     
  1153.     /* wait for    video retrace to start ----- */
  1154.     do
  1155.        asm in  al,dx;
  1156.     while (_AL & 1);
  1157.     
  1158.     /* wait for    video retrace to stop */
  1159.     do
  1160.        asm in  al,dx;
  1161.     while (!(_AL & 1));
  1162.     asm    lodsb;                /* get the character */
  1163.     _BL    = _AL;
  1164.     
  1165.     /* wait for    video retrace to start */
  1166.     do
  1167.        asm in  al,dx;
  1168.     while (_AL & 1);
  1169.     
  1170.     /* ait for video retrace to    stop */
  1171.     do
  1172.        asm in  al,dx;
  1173.     while (!(_AL & 1));
  1174.     asm    lodsb;                /* get the attribute */
  1175.     _BH    = _AL;
  1176.     _AX    = _BX;
  1177.     asm    pop ds;
  1178.     return _AX;
  1179. }
  1180.  
  1181. -------------------------------------------------------------------------
  1182.  
  1183. >Vpoke.  Directly Stuff    16 Bits    into Video RAM.
  1184.  
  1185. void Vpoke(unsigned adr, unsigned chr)
  1186. {
  1187.     if (!SnowStop) poke(VSEG, adr, chr);
  1188.     else    {
  1189.        _DI = adr;           /* offset of video character */
  1190.        _ES = VSEG;           /* video    segment    */
  1191.        asm cld;
  1192.        _BX = chr;           /* the attribute    and character */
  1193.        _DX = 986;           /* video    status port */
  1194.        
  1195.        /* ------ wait for video    retrace    to start ----- */
  1196.        do
  1197.       asm in  al,dx;
  1198.        while (_AL & 1);
  1199.        
  1200.        /* ------ wait for video    retrace    to stop    ----- */
  1201.        do
  1202.       asm in  al,dx;
  1203.        while (!(_AL & 1));
  1204.        _AL = _BL;
  1205.        asm stosb;           /* store    character */
  1206.        
  1207.        /* ------ wait for video    retrace    to start ----- */
  1208.        do
  1209.       asm in  al,dx;
  1210.        while (_AL & 1);
  1211.        
  1212.        /* ------ wait for video    retrace    to stop    ----- */
  1213.        do
  1214.       asm in  al,dx;
  1215.        while (!(_AL & 1));
  1216.        _AL = _BH;
  1217.        asm stosb;           /* store    attribute */
  1218.     }
  1219. }
  1220.  
  1221. -------------------------------------------------------------------------
  1222.  
  1223. >ZapAskBox.  Inverse of    MkAskBox.
  1224.  
  1225. void ZapAskBox(char *FootPrint,int X,int Y,int Width,int Tall,char Shadow)
  1226. {
  1227.     int    X1, Y1;
  1228.  
  1229.  /* Handle Shadow */
  1230.     X1 = X + Width - 1;    Y1 = Y + Tall -    1;
  1231.     if (Y+Tall > 25);
  1232.     else if (Shadow IS 'L' && X    > 1)   { X--;  Y1++; }
  1233.     else if (Shadow IS 'R' && X    < 80)  { X1++; Y1++; }
  1234.  
  1235.  /* Zap    Window */
  1236.     HideCursor(); RestoreBox(X,    Y, X1, Y1, FootPrint);
  1237. }
  1238.  
  1239. -------------------------------------------------------------------------
  1240.  
  1241. ===========================================================================
  1242.  
  1243. >Mouse.h.  Text/Graphics Mouse Access via int86(0x33...).
  1244.  
  1245.    Requires Linking w/ Graphics.Lib ON (even for text-only use).
  1246.  
  1247. ----------------------------------------------------------------------------
  1248.  
  1249. >Mouse Buttons.  A Keys.h Style    Solution to Mouse Buttons.
  1250.  
  1251.    The IBM ScanCode List has a few Holes in it (Codes which can    not be User 
  1252. Generated).  In    Keys.h,    these are the "EK###" values.  Seven of    these have 
  1253. been used in Mouse.h for Button    Selection/Reporting:
  1254.  
  1255.     BTN_ANY    BTN_L    BTN_R    BTN_M    <--- For Both Selecting/Reporting.
  1256.     BTN_LR    BTN_LM    BTN_MR    BTN_LMR <--- For Reporting Only.
  1257.  
  1258.    Obviously, if your mouse has    only 2 buttons,    BTN_LMR    will never be 
  1259. reported.
  1260.  
  1261. ----------------------------------------------------------------------------
  1262.  
  1263. >HideMouse.  Remove the    Graphics Cursor    (usually an arrow).
  1264.  
  1265. #define    HideMouse()        (MouseSwitch(0))
  1266.  
  1267. ----------------------------------------------------------------------------
  1268.  
  1269. >Mouse.  The Generic Mouse Interrupt (33h) --> Access to Mouse Driver.
  1270.  
  1271. void Mouse(int *A, int *B, int *C, int *D)
  1272. {
  1273.     union REGS rg;
  1274.  
  1275.     rg.x.ax = *A; rg.x.bx = *B;    rg.x.cx    = *C; rg.x.dx =    *D;
  1276.     int86(0x33,    &rg, &rg);
  1277.     *A = rg.x.ax; *B = rg.x.bx;    *C = rg.x.cx; *D = rg.x.dx;
  1278. }
  1279.  
  1280.    Not very useful by itself, Mouse() is frequently used in published 
  1281. programs as a crutch to    using int86(0x33...).  See CUJ Vol 9 No.4 (April 91)
  1282. ppgs 46+ for an    example.
  1283.  
  1284. ---------------------------------------------------------------------------
  1285.  
  1286. >MouseAtxy.  Report Mouse Location and Button Press Status.
  1287.  
  1288. int MouseAtxy(int *X, int *Y)
  1289. {
  1290.     union REGS rg;
  1291.  
  1292.     if (!MouseOK()) return 0;
  1293.     rg.x.ax = 3; int86(0x33, &rg, &rg);    *X = rg.x.cx; *Y = rg.x.dx;
  1294.     if (IsTextMode()) {    *X = (*X) / 8 +    1; *Y =    (*Y) / 8 + 1; }
  1295.     else if (getmaxx() IS 319) (*X) /= 2;
  1296.     return (rg.x.bx) ? Handles(-rg.x.bx) : 0;
  1297. }
  1298.  
  1299. ---------------------------------------------------------------------------
  1300.  
  1301. >MouseClicked.  True if    Specified Button was Clicked or    Keys.h for BTN_ANY.
  1302.  
  1303. int MouseClicked(int Button)
  1304. {
  1305.     int    i, n = 0;
  1306.     union REGS rg;
  1307.  
  1308.     if (! _Mouse) return 0; i =    Handles(Button);
  1309.     do { int86(0x28, &rg, &rg);    rg.x.ax    = 3; int86(0x33, &rg, &rg);
  1310.     }  while (rg.x.bx);
  1311.     if (i < 3) {
  1312.        rg.x.ax = 6; rg.x.bx = i; int86(0x33, &rg, &rg);    n = (rg.x.bx > 0);
  1313.     } else while (i--) {
  1314.        n *= 2; rg.x.ax = 6; rg.x.bx = i; int86(0x33, &rg, &rg);
  1315.        n -= (rg.x.bx > 0);
  1316.     }
  1317.     return (n <    0) ? Handles(n)    : n;
  1318. }
  1319.  
  1320. ---------------------------------------------------------------------------
  1321.  
  1322. >MouseClickedxy.  Report Location of Mouse on Last Click of Specified Button.
  1323.  
  1324. int MouseClickedxy(int Button, int *X, int *Y)
  1325. {
  1326.     union REGS rg;
  1327.     
  1328.     if (!MouseOK() || (rg.x.bx = Handles(Button)) IS 3)    return 0;
  1329.     rg.x.ax = 6; int86(0x33, &rg, &rg);
  1330.     *X = rg.x.cx; *Y = rg.x.dx;
  1331.     if (IsTextMode()) {    *X = (*X) / 8 +    1; *Y =    (*Y) / 8 + 1; }
  1332.     else if (getmaxx() IS 319) (*X) /= 2;
  1333.     return (rg.x.bx) ? Handles(-rg.x.bx) : 0;
  1334. }
  1335.  
  1336. ---------------------------------------------------------------------------
  1337.  
  1338. >MouseDeltaxy.  Report Mouse Motion since Last Check.
  1339.  
  1340. void MouseDeltaxy(int *X, int *Y)
  1341. {
  1342.     int    Dx, Dy;
  1343.     union REGS rg;
  1344.  
  1345.     if (!MouseOK()) { *X = *Y =    0; return; }
  1346.     rg.x.ax = 0x1B; int86(0x33,    &rg, &rg); Dx =    rg.x.bx; Dy = rg.x.cx;
  1347.     rg.x.ax = 0x0B; int86(0x33,    &rg, &rg); 
  1348.     *X = (rg.x.cx * Dx)    / 8; *Y    = (rg.x.dx * Dy) / 8; 
  1349.     if (IsTextMode()) {    *X = (*X) / 8 +    1; *Y =    (*Y) / 8 + 1; }
  1350.     else if (getmaxx() IS 319) (*X) /= 2;
  1351. }
  1352.  
  1353. ---------------------------------------------------------------------------
  1354.  
  1355. >MouseOK.  True    if Mouse Driver    is Installed and Responding.
  1356.  
  1357. int MouseOK(void) { return _Mouse; }    /*    Set/Cleared by MouseReSet() */
  1358.  
  1359. ---------------------------------------------------------------------------
  1360.  
  1361. >MousePageSet.  Select which Video Page    the Mouse be Active.
  1362.  
  1363. void MousePageSet(int Which1)
  1364. {
  1365.       union REGS rg;
  1366.       
  1367.       rg.x.ax =    0x1D; rg.x.bx =    Which1;    int86(0x33, &rg, &rg);
  1368. }
  1369.  
  1370. ---------------------------------------------------------------------------
  1371.  
  1372. >MouseReSet.  Reset Mouse Driver & Physical Mouse.
  1373.  
  1374. int MouseReSet(void)
  1375. /*  Resets the mouse.  Returns # of Buttons if Present or 0 if No Mouse. */
  1376. {
  1377.     union REGS rg;
  1378.  
  1379.     rg.x.ax = 0; int86(0x33, &rg, &rg);    if (rg.x.ax IS 0) return 0;
  1380.     _Mouse = 1;    MouseSwitch(-1);
  1381.     return (rg.x.bx IS 0) ? 2 :    (rg.x.bx IS 3) ? 3 : 1;
  1382. }
  1383.  
  1384. ---------------------------------------------------------------------------
  1385.  
  1386. >MouseSpeed.  Set Mouse    Sensitivity & Ballistic    Action.
  1387.  
  1388. void MouseSpeed(int Dx,    int Dy,    int Zoom)
  1389. {
  1390.       union REGS rg;
  1391.       
  1392.       rg.x.ax =    0x1A; rg.x.bx =    Dx; rg.x.cx = Dy; rg.x.dx = Zoom;
  1393.       int86(0x33, &rg, &rg);
  1394. }
  1395.  
  1396. Notes:
  1397.     1. Dx & Dy are in "Mouse Tics" ("mickeys") / ( 8 Pixels).  In other    
  1398.        words, the fastest rate is one text character cell/mickey.
  1399.     2. Dx & Dy default to 8 & 16, respectively.     Large Numbers Move Slower.
  1400.     3. Zoom is the mickeys/second above    which the Mouse    moves Double Speed.
  1401.     4. Zoom defaults to    64 mickeys/second.
  1402.     5. This "Mickey Mouse" business was    created    by MicroSoft.
  1403.  
  1404. ---------------------------------------------------------------------------
  1405.  
  1406. >MouseSwitch.  The Business End    of HideMouse/ShowMouse.
  1407.  
  1408. int MouseSwitch(int Flag)
  1409. {
  1410.     union REGS rg;
  1411.     static int Cd_mouse    = 1;
  1412.  
  1413.     if (Flag IS    -1) Cd_mouse = 0;
  1414.     if (!Flag && !Cd_mouse) return 0;
  1415.     if (Flag &&    Cd_mouse) return 1;
  1416.     rg.x.ax = 1    + !Flag; int86(0x33, &rg, &rg);    Cd_mouse = !Cd_mouse;
  1417.     return !Cd_mouse;
  1418. }
  1419.  
  1420. ---------------------------------------------------------------------------
  1421.  
  1422. >MouseToxy.  Relocate the Mouse    Cursor.
  1423.  
  1424. void MouseToxy(int X, int Y)
  1425. {
  1426.     union REGS rg;
  1427.     
  1428.     if (!MouseOK()) { if (IsTextMode())    Gotoxy(X, Y); return; }
  1429.     if (IsTextMode()) {    rg.x.cx    = --X *    8; rg.x.dx = --Y * 8; }
  1430.     else {
  1431.        if (getmaxx() ==    319) X *= 2;    /*    Adjust for virtual coordinates */
  1432.        rg.x.cx = X; rg.x.dx = Y; 
  1433.     }
  1434.     rg.x.ax = 4; int86(0x33, &rg, &rg);
  1435. }
  1436.  
  1437. ---------------------------------------------------------------------------
  1438.  
  1439. >MouseTrap.  True if mouse Cursor is Inside a Specified    Rectangle.
  1440.  
  1441. int MouseTrap(int Left,    int Top, int Right, int    Bottom)
  1442. {
  1443.     int    X, Y;
  1444.     
  1445.     if (MouseOK()) MouseAtxy(&X, &Y); else return 0;
  1446.     return((X >= Left && X <= Right && Y >= Top    && Y <=    Bottom)    ? 1 : 0);
  1447. }
  1448.  
  1449. ---------------------------------------------------------------------------
  1450.  
  1451. >MouseWait4User.  A Kbq_read() for the Mouse.
  1452.  
  1453. int MouseWait4User(void)
  1454. {
  1455.     int    c, X, Y;
  1456.  
  1457.     if (IsTextMode()) {    Getxy(&X, &Y); MouseToxy(X, Y);    }
  1458.     for    (c = 0;    !c; )
  1459.        if (!(c = Kbq_poll()) &&    !(c = MouseClicked(BTN_ANY)) &&
  1460.       IsTextMode())    { MouseAtxy(&X,    &Y); Gotoxy(X, Y); }
  1461.     return c;
  1462. }
  1463.  
  1464. ---------------------------------------------------------------------------
  1465.  
  1466. >ShowMouse.  Display the Graphics Cursor (usually an arrow).
  1467.  
  1468. #define    ShowMouse()        (MouseSwitch(1))
  1469.  
  1470. ============================================================================
  1471.  
  1472. >Rampage.h.  Transparently Handle a File & RAM Editing Buffer.
  1473.  
  1474.    This    routine    isn't for light    weights.  It can manage    up to a    full page 
  1475. (64K) of DOS RAM and edit text files up    to 32K Lines in    length (500+ printed 
  1476. pages).
  1477.  
  1478.    Only    the LARGE model    is supported (far pointers in the SMALL    model get 
  1479. crazy).     Rampage.h provides access to the "Engine" via a set of    Macros.     
  1480. Nothing    fancy and you may well want to change their Names, expand them into
  1481. functions or whatever.
  1482.  
  1483.    Default RAM Page size is 64K, but this can be altered by setting 
  1484. "extern    long SizeOfRamPage" to something smaller, especially if    your line 
  1485. lengths    are short and your RAM is too.
  1486.  
  1487.    Lines larger    than 255 characters get    cropped.  It is    assumed    that the 
  1488. Fetch Buffer you pass in is large enough to hold your longest line (or the 255 
  1489. character stub).
  1490.  
  1491.    A lot goes on inside    the Engine (See    Rampage.c for details).     Fromt the 
  1492. Outside, it acts pretty    much as    you would expect.  
  1493.  
  1494.    About the only "Surprise" is    when you "Push"    a long line (longer than seen
  1495. before)    or the RAM Page    gets full.  Both of those cause    the Enginer to "Go 
  1496. Away" for a while, saving what you have    done and freeing up the    RAM Page for 
  1497. more work.
  1498.    
  1499. ============================================================================
  1500.  
  1501. >Close.  Save Your Changes, Close the File, Free all Allocated RAM.
  1502.  
  1503. #define    Close()            (Rampage("Close", NULL, 1))
  1504.  
  1505. ----------------------------------------------------------------------------
  1506.  
  1507. >CloseNoSave.  Discard UnSaved Edits, Close File, Free Allocated RAM.
  1508.  
  1509. #define    CloseNoSave()        (Rampage("Close", NULL, 2))
  1510.  
  1511. ----------------------------------------------------------------------------
  1512.  
  1513. >DeleteLine.  Snip Out & Discard a Specified Line.
  1514.  
  1515. #define    DeleteLine(x)        (Rampage("Delete", NULL,    x))
  1516.  
  1517. ----------------------------------------------------------------------------
  1518.  
  1519. >Fetch.  Get a Specified Line of Text as a String.
  1520.  
  1521. #define    Fetch(x,y)        (Rampage("Fetch", x, y))
  1522.  
  1523. ----------------------------------------------------------------------------
  1524.  
  1525. >Load.  Find, Open and Prepare a File for Action.  (Save Previous Edits)
  1526.  
  1527. #define    Load(x)            (Rampage("Load", x, 1))
  1528.  
  1529. ----------------------------------------------------------------------------
  1530.  
  1531. >LoadNoSave.  Find, Open and Prepare a File for    Action.     (Trash    Old Edits)
  1532.  
  1533. #define    LoadNoSave(x)        (Rampage("Load",    x, 2))
  1534.  
  1535. ----------------------------------------------------------------------------
  1536.  
  1537. >Push.  Place an Altered Line into the RAM Page.
  1538.  
  1539. #define    Push(x,y)        (Rampage("Push", x, y))
  1540.  
  1541. ----------------------------------------------------------------------------
  1542.  
  1543. >Save.  Post Edits held    in the RAM Page    into the File.
  1544.  
  1545. #define    Save()            (Rampage("Save", NULL,    1))
  1546.  
  1547. Note: The Old (unaltered) File becomes a ".BAK", and a new File    is created 
  1548. from the contents of the Old File and the RAM Page, which is then cleared.
  1549.  
  1550. ----------------------------------------------------------------------------
  1551.  
  1552. >SaveAs.  Save Your Edits, Shell Out & Copy to a New Name & Load That.
  1553.  
  1554. #define    SaveAs(x)        (Rampage("Save", x, 2))
  1555.  
  1556. ----------------------------------------------------------------------------
  1557.  
  1558.