home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / tcl / tclsrc / c / WimpDoc < prev    next >
Text File  |  1996-03-26  |  12KB  |  465 lines

  1. /* Wimp document window commands for tcl */
  2. /* (c) C.T.Stretch */
  3. /* Wed,20 Jul 1994 */
  4.  
  5. #include "h.WInt"
  6. #include "h.colourtrans"
  7.  
  8. typedef struct line
  9. { short l,r;
  10.   char t[4];
  11. } line;
  12.  
  13. typedef struct document
  14. { struct document *next;
  15.   struct view *viewlist;
  16.   line ***lines;
  17.   char *name,*title,*close;
  18.   tcl_menu *menu;
  19.   int nl,mnl;
  20.   int width,ht,ps,lmargin,rmargin,indent,just,proc,up,down,setp;
  21.   os_colour fg,bg;
  22.   font_f font;
  23.   font_table ft;
  24. } document;
  25.  
  26. Tcl_HashTable documentTable;
  27.  
  28. static document *documentlist;
  29. static int overlap;
  30. static wimp_window tw=
  31. {
  32.   {240,198,1106,800},
  33.   0, 0, (wimp_w)-1, 0x7f01000f,
  34.   0x7, 0x2, 0x7, 0xFF,
  35.   0x3, 0x1, 0xc, 0x0,
  36.   {0,-784,1280,0},
  37.   0x13d, 0x3000, (osspriteop_area*)0x1, 64, 512,
  38.   "",
  39.   0
  40. };
  41.  
  42. /*
  43.  *  --
  44.  *
  45.  *
  46.  *
  47.  *
  48.  *
  49.  * Results:
  50.  *      None.
  51.  *
  52.  * Side effects:
  53.  *      None.
  54.  *
  55. */
  56.  
  57. bool document_redraw(void)
  58. { document *t;
  59.   view *v;
  60.   wimp_draw *d=(wimp_draw*)█
  61.   for(t=documentlist;t;t=t->next) for(v=t->viewlist;v;v=v->next)
  62.   if(v->w==block.redraw.w)
  63.   { int more=wimp_redraw_window(d);
  64.     int bx,by,tl,bl,i;
  65.     bx=d->box.x0-d->xscroll;
  66.     by=d->box.y1-d->yscroll;
  67.     while(more)
  68.     { colourtrans_set_gcol(t->bg,colourtrans_SET_BG,os_ACTION_OVERWRITE,0);
  69.       os_writec(os_VDU_CLG);
  70.       tl=(by-d->clip.y1+t->down)/t->ht;
  71.       if(tl<0) tl=0;
  72.       bl=1+(by-d->clip.y0+t->up)/t->ht;
  73.       if(bl>t->nl) bl=t->nl;
  74.       for(i=tl;i<bl;i++)
  75.       { line *l=t->lines[i>>8][i&0xFF];
  76.         colourtrans_set_font_colours(t->font,t->bg,t->fg,14,0,0,0);
  77.         if(l->r)
  78.         { os_plot(os_MOVE_TO,bx+l->r,by-i*t->ht);
  79.           font_paint(t->font,l->t,font_OS_UNITS|font_JUSTIFY,
  80.             bx+l->l,by-i*t->ht,0,0,0);
  81.         }
  82.         else
  83.         font_paint(t->font,l->t,font_OS_UNITS,bx+l->l,by-i*t->ht,0,0,0);
  84.       }
  85.       more=wimp_get_rectangle(d);
  86.     }
  87.     return TRUE;
  88.   }
  89.   return FALSE;
  90. }
  91.  
  92. tcl_menu *document_menu(void)
  93. { document *t;
  94.   view *v;
  95.   for(t=documentlist;t;t=t->next) for(v=t->viewlist;v;v=v->next)
  96.   if(v->w==block.pointer.w)
  97.   { substr['w'-'a']=t->name;
  98.     return t->menu;
  99.   }
  100.   return FALSE;
  101. }
  102.  
  103. static void dropview(view *v,document *t)
  104. { wimp_delete_window(v->w);
  105.   unlink(&(t->viewlist),v);
  106.   ckfree(v);
  107. }
  108.  
  109. static void document_free(document *t)
  110. { int i;
  111.   for(i=0;i<t->nl;i++) ckfree(t->lines[i>>8][i&0xFF]);
  112.   for(i=0;i<(t->nl+255)>>8;i++) ckfree(t->lines[i]);
  113.   ckfree(t->lines);
  114.   ckfree(t->name);
  115.   if(t->title!=progname) ckfree(t->title);
  116.   ckfree(t->close);
  117.   if(t->menu!=menu_NONE) menu_free(t->menu);
  118.   release_fonts(&(t->ft));
  119.   ckfree(t);
  120.   substr['w'-'a']=0;
  121. }
  122.  
  123. bool document_close(void)
  124. { document *d;
  125.   view *v;
  126.   Tcl_HashEntry *p;
  127.   int n;
  128.   for(d=documentlist;d;d=d->next) for(v=d->viewlist;v;v=v->next)
  129.   if(v->w==block.close.w)
  130.   { if(d->viewlist->next) { dropview(v,d);return TRUE;}
  131.     else
  132.     { if(d->close)
  133.       { substr['w'-'a']=d->name;
  134.         checkEval(d->close,"document close");
  135.         n=getconstant(w_Interp->result);
  136.         if(n==1) return TRUE;
  137.         if(n!=0) {dropview(v,d);return TRUE;}
  138.       }
  139.       dropview(v,d);
  140.       p=Tcl_FindHashEntry(&documentTable,d->name);
  141.       if(!p)
  142.       { msg("Odd close request",0,0);
  143.         return TRUE;
  144.       }
  145.       Tcl_DeleteHashEntry(p);
  146.       unlink(&documentlist,d);
  147.       substr['w'-'a']=0;
  148.       document_free(d);
  149.       return TRUE;
  150.     }
  151.   }
  152.   return FALSE;
  153. }
  154.  
  155. static void setext(document *d,int m)
  156. { view *v;
  157.   os_box b;
  158.   b.x0=0;b.x1=d->width;b.y1=d->ht;b.y0=-d->ht*d->nl+d->ht/2;
  159.   for(v=d->viewlist;v;v=v->next)
  160.   { wimp_set_extent(v->w,&b);
  161.     wimp_force_redraw(v->w,0,b.y0,d->width,d->up-d->ht*m);
  162.   }
  163.   v=d->viewlist;
  164.   if(v)
  165.   { wimp_open *wo=(wimp_open*)█
  166.     block.open.w=v->w;
  167.     wimp_get_window_state((wimp_window_state*)&block);
  168.     wo->yscroll=b.y0+wo->visible.y1-wo->visible.y0;
  169.     wimp_open_window(wo);
  170.   }
  171. }
  172.  
  173. static void setcolour(char *p,os_colour fg,os_colour bg)
  174. { p[0]=19;
  175.   p[1]=bg>>8;p[2]=bg>>16;p[3]=bg>>24;
  176.   p[4]=fg>>8;p[5]=fg>>16;p[6]=fg>>24;
  177.   p[7]=14;
  178. }
  179.  
  180. static line *addline(document *t,int n)
  181. { line *l;
  182.   if((t->nl&0xFF)==0)
  183.   { if((t->nl>>8)>=t->mnl)
  184.     { line ***lt=ckalloc((256+t->mnl)*sizeof(line**));
  185.       memcpy(lt,t->lines,t->mnl*sizeof(line**));
  186.       free(t->lines);
  187.       t->lines=lt;
  188.       t->mnl+=256;
  189.     }
  190.     t->lines[t->nl>>8]=ckalloc(256*sizeof(line*));
  191.   }
  192.   l=ckalloc(sizeof(line)+n-3);
  193.   t->lines[t->nl>>8][t->nl&0xFF]=l;
  194.   t->nl++;
  195.   return l;
  196. }
  197.  
  198. static int linelen(document *t,char **args,int nargs)
  199. { int n=nargs-1,i;
  200.   char *q;
  201.   for(i=0;i<nargs;i++) n+=strlen(args[i]);
  202.   if(t->proc)
  203.   { for(i=0;i<nargs;i++)
  204.     { char *p;
  205.       for(p=args[i];*p;p++) if(*p=='|')
  206.       { q=p+1;p=strchr(q,'|');
  207.         if(!p) return -1;
  208.         n-=p-q+2;
  209.         switch(*q)
  210.         { case '|':n++;break;
  211.           case 'f':case 'F':n+=2;break;
  212.           case 'c':n+=8;break;
  213.          default:return -1;
  214.         }
  215.       }
  216.     }
  217.   }
  218.   if(n<0) return 0;
  219.   return n;
  220. }
  221.  
  222.  
  223. static void getline(char *out,document *t,char **args,int nargs)
  224. { int i;
  225.   char *q;
  226.   if(!nargs) {*out=0;return;}
  227.   if(t->proc)
  228.   { for(i=0;i<nargs;i++)
  229.     { char *p;
  230.       os_colour c;
  231.       for(p=args[i];*p;p++) if(*p=='|')
  232.       { q=p+1;p=strchr(q,'|');
  233.         switch(*q)
  234.         { case '|':*out++='|';break;
  235.           case 'f':
  236.           case 'F':*out++=26;
  237.                    *p=0;
  238.                    *out++=find_font(q,t->ps,&(t->ft));
  239.                    *p='|';
  240.                    break;
  241.           case 'c':*p=0;
  242.                    c=getcolour(q+1);
  243.                    *p='|';
  244.                    setcolour(out,c,t->bg);out+=8;
  245.                    break;
  246.         }
  247.       }
  248.       else
  249.       { if(*p<' '||*p=='\b') *p=' ';
  250.         *out++=*p;
  251.       }
  252.       *out++=' ';
  253.     }
  254.     out[-1]=0;
  255.   }
  256.   else
  257.   { q=out;
  258.     out+=sprintf(out,"%s",args[0]);
  259.     for(i=1;i<nargs;i++) out+=sprintf(out," %s",args[i]);
  260.     for(;*q;q++) if(*q<' '||*q=='\b') *q=' ';
  261.   }
  262. }
  263.  
  264. static char *splitline(document *t,char *p,int left,int width)
  265. { line *l;
  266.   char *sp,*q;
  267.   int n=0;
  268.   font_scan_block fsb[1];
  269.   static os_colour col;
  270.   static font_f    fnt;
  271.   bool nospace=FALSE;
  272.   if(!p) { col=t->fg;fnt=t->font;return 0;};
  273.   fsb->space.x=0;fsb->space.y=0;fsb->letter.x=0;fsb->letter.y=0;
  274.   fsb->split_char=' ';
  275.   sp=0;
  276.   fsb->bbox.x0=0;fsb->bbox.y0=0;fsb->bbox.x1=0;fsb->bbox.y1=0;
  277.   font_scan_string(fnt,p,font_GIVEN_BLOCK|font_RETURN_BBOX|font_GIVEN_FONT,
  278.     width*font_OS_UNIT,INT_MAX,fsb,0,0,&sp,0,0,0);
  279.   if(p==sp&&*p)
  280.   { nospace=TRUE;
  281.     font_scan_string(fnt,p,font_RETURN_CARET_POS|font_GIVEN_FONT,
  282.         width*font_OS_UNIT,INT_MAX,0,0,0,&sp,0,0,0);
  283.     if(p==sp) { msg("Nothing fits",0,0);sp=p+strlen(p);}
  284.   }
  285.   if(col!=t->fg) n+=8;
  286.   if(fnt!=t->font) n+=2;
  287.   l=addline(t,sp-p+n);
  288.   q=l->t;
  289.   l->l=left;l->r=0;
  290.   if(fnt!=t->font) { *q++=26;*q++=fnt;}
  291.   if(col!=t->fg) { setcolour(q,col,t->bg);q+=8;}
  292.   memcpy(q,p,sp-p);q[sp-p]=0;
  293.   while(*sp==' ') sp++;
  294.   if(*sp&&t->just) l->r=t->rmargin;
  295.   if(nospace)
  296.   { fsb->space.x=0;fsb->space.y=0;fsb->letter.x=0;fsb->letter.y=0;
  297.     fsb->split_char=-1;
  298.     font_scan_string(fnt,l->t,font_RETURN_BBOX|font_GIVEN_BLOCK|font_GIVEN_FONT,
  299.       INT_MAX,INT_MAX,fsb,0,0,0,0,0,0);
  300.   }
  301.   mp_to_os(&(fsb->bbox));
  302.   if(fsb->bbox.y0<t->down) t->down=fsb->bbox.y0;
  303.   if(fsb->bbox.y1>t->up) t->up=fsb->bbox.y1;
  304.   for(p=l->t;*p;p++) switch(*p)
  305.   { case 26:fnt=*++p;break;
  306.     case 19:col=(p[6]<<24)+(p[5]<<16)+(p[4]<<8);
  307.             p+=7;
  308.             break;
  309.   }
  310.   return sp;
  311. }
  312.  
  313. int w_TextCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
  314. { document *t;
  315.   Tcl_HashEntry *p;
  316.   if(argc<3) return wrong(WNA,"w_text <name> <command> ...");
  317. /* *********** create a document *************** */
  318.   if(!strcmp(argv[2],"create"))
  319.   { int new=0,m;
  320.     p=Tcl_CreateHashEntry(&documentTable,argv[1],&new);
  321.     if(!new) return wrong("Text already exists: ",argv[1]);
  322.     t=ckcalloc(sizeof(document));
  323.     t->name=scopy(argv[1]);
  324.     t->title=progname;
  325.     t->fg=os_COLOUR_BLACK;
  326.     t->bg=os_COLOUR_WHITE;
  327.     t->menu=menu_NONE;
  328.     for(m=3;m<argc-1;m++)
  329.     { if(!strcmp(argv[m],"-width"))
  330.       { t->width=getsize(argv[++m],os_INCH);
  331.         continue;
  332.       }
  333.       if(!strcmp(argv[m],"-height"))
  334.       { t->ht=getsize(argv[++m],os_INCH);
  335.         continue;
  336.       }
  337.       if(!strcmp(argv[m],"-size"))
  338.       { t->ps=getsize(argv[++m],16*72);
  339.         continue;
  340.       }
  341.       if(!strcmp(argv[m],"-bg"))
  342.       { t->bg=getcolour(argv[++m]);
  343.         continue;
  344.       }
  345.       if(!strcmp(argv[m],"-fg"))
  346.       { t->fg=getcolour(argv[++m]);
  347.         continue;
  348.       }
  349.       if(!strcmp(argv[m],"-menu"))
  350.       { t->menu=menu_make(argv[++m],t->name);
  351.         if(t->menu==0)
  352.         { t->menu=menu_NONE;
  353.           return TCL_ERROR;
  354.         }
  355.         continue;
  356.       }
  357.       if(!strcmp(argv[m],"-title")) { t->title=scopy(argv[++m]);continue;}
  358.       if(!strcmp(argv[m],"-close")) { t->close=scopy(argv[++m]);continue;}
  359.     }
  360.     if(t->width<=0) t->width=800;
  361.     if(t->ps<=0) t->ps=20*16;
  362.     if(t->ht<=0) t->ht=t->ps/6;
  363.     t->rmargin=t->width;
  364.     t->font=find_font("fn",t->ps,&(t->ft));
  365.     if(!t->font) return wrong("Can't open any font",0);
  366.     t->next=documentlist;
  367.     documentlist=t;
  368.     Tcl_SetHashValue(p,t);
  369.     return TCL_OK;
  370.   }
  371.   p=Tcl_FindHashEntry(&documentTable,argv[1]);
  372.   if(!p) return wrong("No such document: ",argv[1]);
  373.   t=(document*)Tcl_GetHashValue(p);
  374. /* *********** open a window *************** */
  375.   if(!strcmp(argv[2],"open"))
  376.   { view *v=ckalloc(sizeof(view));
  377.     int x,y;
  378.     screensize(&x,&y);
  379.     if(overlap>y/2-INSET) overlap=0;
  380.     tw.title_data.indirected_text.text=t->title;
  381.     tw.title_data.indirected_text.validation=(char*)-1;
  382.     tw.title_data.indirected_text.size=strlen(t->title);
  383.     tw.extent.x1=t->width;
  384.     tw.extent.y1=t->ht;
  385.     tw.extent.y0=-(t->nl)*t->ht+t->ht/2;
  386.     tw.visible.y1=y-INSET-overlap;
  387.     tw.visible.y0=tw.visible.y1-(tw.extent.y1-tw.extent.y0);
  388.     if(tw.visible.y0<INSET) tw.visible.y0=INSET;
  389.     tw.yscroll=tw.extent.y1;
  390.     tw.visible.x0=INSET+overlap/2;
  391.     tw.visible.x1=tw.visible.x0+t->width;
  392.     if(tw.visible.x1>x-INSET) tw.visible.x1=x-INSET;
  393.     v->w=wimp_create_window(&tw);
  394.     v->next=t->viewlist;
  395.     t->viewlist=v;
  396.     block.open.w=v->w;
  397.     wimp_get_window_state((wimp_window_state*)&block);
  398.     wimp_open_window((wimp_open*)&block);
  399.     overlap+=40;
  400.     return TCL_OK;
  401.   }
  402. /* *********** set options *************** */
  403.   if(!strcmp(argv[2],"options"))
  404.   { int i;
  405.     for(i=3;i<argc;i++)
  406.     { if(argv[i][0]=='-') switch(argv[i][1])
  407.       { case 'l':t->lmargin=getsize(argv[i]+2,os_INCH);continue;
  408.         case 'r':t->rmargin=t->width-getsize(argv[i]+2,os_INCH);continue;
  409.         case 'i':t->indent=getsize(argv[i]+2,os_INCH);continue;
  410.         case 'j':t->just=(getconstant(argv[i]+2)==1);continue;
  411.         case 'p':t->proc=(getconstant(argv[i]+2)==1);continue;
  412.         case 'L':t->setp=0;continue;
  413.         case 'C':t->setp=1;continue;
  414.         case 'R':t->setp=2;continue;
  415.       }
  416.       return wrong("Bad document option: ",argv[i]);
  417.     }
  418.     if((t->indent>=t->rmargin)||(t->lmargin>=t->rmargin))
  419.     { t->indent=0;t->lmargin=0;t->rmargin=t->width;
  420.     }
  421.     return TCL_OK;
  422.   }
  423. /* *********** print a line *************** */
  424.   if(!strcmp(argv[2],"print"))
  425.   { int n=linelen(t,argv+3,argc-3);
  426.     int m=t->nl;
  427.     font_scan_block fsb[1];
  428.     line *l;
  429.     if(n<0) return wrong("bad '|' sequence",0);
  430.     l=addline(t,n);l->r=0;
  431.     getline(l->t,t,argv+3,argc-3);
  432.     fsb->space.x=0;fsb->space.y=0;fsb->letter.x=0;fsb->letter.y=0;
  433.     fsb->split_char=-1;
  434.     font_scan_string(t->font,l->t,
  435.       font_RETURN_BBOX|font_GIVEN_BLOCK|font_GIVEN_FONT,
  436.         INT_MAX,INT_MAX,fsb,0,0,0,0,0,0);
  437.     mp_to_os(&(fsb->bbox));
  438.     if(fsb->bbox.y0<t->down) t->down=fsb->bbox.y0;
  439.     if(fsb->bbox.y1>t->up) t->up=fsb->bbox.y1;
  440.     l->l=t->lmargin+
  441.       t->setp*((t->rmargin-t->lmargin)-(fsb->bbox.x1-fsb->bbox.x0))/2;
  442.     setext(t,m);
  443.     return TCL_OK;
  444.   }
  445. /* *********** write a paragraph *************** */
  446.   if(!strcmp(argv[2],"write"))
  447.   { int n;
  448.     int m=t->nl;
  449.     char *p,*q;
  450.     n=linelen(t,argv+3,argc-3);
  451.     if(n<0) return wrong("bad '|' sequence",0);
  452.     p=ckalloc(n+1);
  453.     getline(p,t,argv+3,argc-3);
  454.     splitline(t,0,0,0);
  455.     q=splitline(t,p,t->indent,t->rmargin-t->indent);
  456.     for(;*q;) q=splitline(t,q,t->lmargin,t->rmargin-t->lmargin);
  457.     ckfree(p);
  458.     setext(t,m);
  459.     return TCL_OK;
  460.   }
  461. /* *********** unknown command *************** */
  462.   return wrong("unknown w_text command: ",argv[2]);
  463. }
  464.  
  465.